Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Corporea string item loading is done client-side #4249

Draft
wants to merge 7 commits into
base: 1.19.x
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;

import vazkii.botania.network.TriConsumer;
import vazkii.botania.network.clientbound.*;
import vazkii.botania.network.serverbound.*;
Expand All @@ -25,7 +24,7 @@ public final class FabricPacketHandler {
public static void init() {
ServerPlayNetworking.registerGlobalReceiver(DodgePacket.ID, makeServerBoundHandler(DodgePacket::decode, DodgePacket::handle));
ServerPlayNetworking.registerGlobalReceiver(IndexKeybindRequestPacket.ID, makeServerBoundHandler(IndexKeybindRequestPacket::decode, IndexKeybindRequestPacket::handle));
ServerPlayNetworking.registerGlobalReceiver(IndexStringRequestPacket.ID, makeServerBoundHandler(IndexStringRequestPacket::decode, IndexStringRequestPacket::handle));
ServerPlayNetworking.registerGlobalReceiver(IndexRequestPacket.ID, makeServerBoundHandler(IndexRequestPacket::decode, IndexRequestPacket::handle));
ServerPlayNetworking.registerGlobalReceiver(JumpPacket.ID, makeServerBoundHandler(JumpPacket::decode, JumpPacket::handle));
ServerPlayNetworking.registerGlobalReceiver(LeftClickPacket.ID, makeServerBoundHandler(LeftClickPacket::decode, LeftClickPacket::handle));
}
Expand All @@ -47,6 +46,7 @@ private static <T> ClientPlayNetworking.PlayChannelHandler makeClientBoundHandle
return (_client, _handler, buf, _responseSender) -> handler.accept(decoder.apply(buf));
}

private FabricPacketHandler() {}
private FabricPacketHandler() {
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import net.minecraftforge.network.NetworkEvent;
import net.minecraftforge.network.NetworkRegistry;
import net.minecraftforge.network.simple.SimpleChannel;

import vazkii.botania.network.TriConsumer;
import vazkii.botania.network.clientbound.*;
import vazkii.botania.network.serverbound.*;
Expand All @@ -27,30 +26,19 @@ public class ForgePacketHandler {
public static void init() {
int i = 0;
// Serverbound
CHANNEL.registerMessage(i++, DodgePacket.class, DodgePacket::encode, DodgePacket::decode,
makeServerBoundHandler(DodgePacket::handle));
CHANNEL.registerMessage(i++, IndexKeybindRequestPacket.class, IndexKeybindRequestPacket::encode, IndexKeybindRequestPacket::decode,
makeServerBoundHandler(IndexKeybindRequestPacket::handle));
CHANNEL.registerMessage(i++, IndexStringRequestPacket.class, IndexStringRequestPacket::encode, IndexStringRequestPacket::decode,
makeServerBoundHandler(IndexStringRequestPacket::handle));
CHANNEL.registerMessage(i++, JumpPacket.class, JumpPacket::encode, JumpPacket::decode,
makeServerBoundHandler(JumpPacket::handle));
CHANNEL.registerMessage(i++, LeftClickPacket.class, LeftClickPacket::encode, LeftClickPacket::decode,
makeServerBoundHandler(LeftClickPacket::handle));
CHANNEL.registerMessage(i++, DodgePacket.class, DodgePacket::encode, DodgePacket::decode, makeServerBoundHandler(DodgePacket::handle));
CHANNEL.registerMessage(i++, IndexKeybindRequestPacket.class, IndexKeybindRequestPacket::encode, IndexKeybindRequestPacket::decode, makeServerBoundHandler(IndexKeybindRequestPacket::handle));
CHANNEL.registerMessage(i++, IndexRequestPacket.class, IndexRequestPacket::encode, IndexRequestPacket::decode, makeServerBoundHandler(IndexRequestPacket::handle));
CHANNEL.registerMessage(i++, JumpPacket.class, JumpPacket::encode, JumpPacket::decode, makeServerBoundHandler(JumpPacket::handle));
CHANNEL.registerMessage(i++, LeftClickPacket.class, LeftClickPacket::encode, LeftClickPacket::decode, makeServerBoundHandler(LeftClickPacket::handle));

// Clientbound
CHANNEL.registerMessage(i++, AvatarSkiesRodPacket.class, AvatarSkiesRodPacket::encode, AvatarSkiesRodPacket::decode,
makeClientBoundHandler(AvatarSkiesRodPacket.Handler::handle));
CHANNEL.registerMessage(i++, BotaniaEffectPacket.class, BotaniaEffectPacket::encode, BotaniaEffectPacket::decode,
makeClientBoundHandler(BotaniaEffectPacket.Handler::handle));
CHANNEL.registerMessage(i++, GogWorldPacket.class, GogWorldPacket::encode, GogWorldPacket::decode,
makeClientBoundHandler(GogWorldPacket.Handler::handle));
CHANNEL.registerMessage(i++, ItemAgePacket.class, ItemAgePacket::encode, ItemAgePacket::decode,
makeClientBoundHandler(ItemAgePacket.Handler::handle));
CHANNEL.registerMessage(i++, SpawnGaiaGuardianPacket.class, SpawnGaiaGuardianPacket::encode, SpawnGaiaGuardianPacket::decode,
makeClientBoundHandler(SpawnGaiaGuardianPacket.Handler::handle));
CHANNEL.registerMessage(i++, UpdateItemsRemainingPacket.class, UpdateItemsRemainingPacket::encode, UpdateItemsRemainingPacket::decode,
makeClientBoundHandler(UpdateItemsRemainingPacket.Handler::handle));
CHANNEL.registerMessage(i++, AvatarSkiesRodPacket.class, AvatarSkiesRodPacket::encode, AvatarSkiesRodPacket::decode, makeClientBoundHandler(AvatarSkiesRodPacket.Handler::handle));
CHANNEL.registerMessage(i++, BotaniaEffectPacket.class, BotaniaEffectPacket::encode, BotaniaEffectPacket::decode, makeClientBoundHandler(BotaniaEffectPacket.Handler::handle));
CHANNEL.registerMessage(i++, GogWorldPacket.class, GogWorldPacket::encode, GogWorldPacket::decode, makeClientBoundHandler(GogWorldPacket.Handler::handle));
CHANNEL.registerMessage(i++, ItemAgePacket.class, ItemAgePacket::encode, ItemAgePacket::decode, makeClientBoundHandler(ItemAgePacket.Handler::handle));
CHANNEL.registerMessage(i++, SpawnGaiaGuardianPacket.class, SpawnGaiaGuardianPacket::encode, SpawnGaiaGuardianPacket::decode, makeClientBoundHandler(SpawnGaiaGuardianPacket.Handler::handle));
CHANNEL.registerMessage(i++, UpdateItemsRemainingPacket.class, UpdateItemsRemainingPacket::encode, UpdateItemsRemainingPacket::decode, makeClientBoundHandler(UpdateItemsRemainingPacket.Handler::handle));
}

private static <T> BiConsumer<T, Supplier<NetworkEvent.Context>> makeServerBoundHandler(TriConsumer<T, MinecraftServer, ServerPlayer> handler) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,12 @@

import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;

import org.jetbrains.annotations.Nullable;

import vazkii.botania.api.ServiceUtil;

import java.util.Collections;
Expand Down Expand Up @@ -54,7 +53,7 @@ default CorporeaRequestMatcher createMatcher(String name) {

/**
* Requests items from the network associated with {@code spark}.
*
*
* @param matcher Specifies what you want to request. See {@link #createMatcher} to create one.
* @param itemCount Specifies the maximum amount you want to request. If -1, the amount is unlimited.
* @param requestor The entity that initiated this request, if there is one.
Expand Down Expand Up @@ -89,5 +88,13 @@ default int signalStrengthForRequestSize(int requestSize) {
return 0;
}

default <T extends CorporeaRequestMatcher> void registerRequestMatcher(ResourceLocation id, Class<T> clazz, Function<CompoundTag, T> deserializer) {}
/**
* @deprecated Use the overload that can ser/de from a buffer also
*/
@Deprecated
default <T extends CorporeaRequestMatcher> void registerRequestMatcher(ResourceLocation id, Class<T> clazz, Function<CompoundTag, T> nbtDeserializer) {
}

default <T extends CorporeaRequestMatcher> void registerRequestMatcher(ResourceLocation id, Class<T> clazz, Function<CompoundTag, T> nbtDeserializer, Function<FriendlyByteBuf, T> bufDeserializer) {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
package vazkii.botania.api.corporea;

import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.ItemStack;

Expand All @@ -18,7 +19,6 @@
* An interface for a Corporea Request matcher. Accepts an ItemStack and returns whether it fulfills the request.
*/
public interface CorporeaRequestMatcher extends Predicate<ItemStack> {

/**
* Returns whether the given stack matches the request's criteria.
*/
Expand All @@ -32,6 +32,11 @@ default boolean test(ItemStack stack) {
*/
default void writeToNBT(CompoundTag tag) {}

/**
* Serialize over the wire, for requesting an item from an index.
*/
default void writeToBuf(FriendlyByteBuf buf) {}

/**
* Returns the pretty name of the requested item, for printing request feedback on Corporea Indexes.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@
*/
package vazkii.botania.common.block.block_entity.corporea;

import it.unimi.dsi.fastutil.ints.IntObjectPair;

import net.minecraft.ChatFormatting;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
Expand All @@ -27,7 +30,10 @@
import vazkii.botania.common.advancements.CorporeaRequestTrigger;
import vazkii.botania.common.block.block_entity.BotaniaBlockEntities;
import vazkii.botania.common.helper.MathHelper;
import vazkii.botania.network.serverbound.IndexStringRequestPacket;
import vazkii.botania.common.impl.corporea.matcher.CorporeaConstantMatcher;
import vazkii.botania.common.impl.corporea.matcher.CorporeaItemStackMatcher;
import vazkii.botania.common.impl.corporea.matcher.CorporeaStringMatcher;
import vazkii.botania.network.serverbound.IndexRequestPacket;
import vazkii.botania.xplat.ClientXplatAbstractions;
import vazkii.botania.xplat.XplatAbstractions;

Expand All @@ -42,7 +48,7 @@ public class CorporeaIndexBlockEntity extends BaseCorporeaBlockEntity implements
private static final Set<CorporeaIndexBlockEntity> serverIndexes = Collections.newSetFromMap(new WeakHashMap<>());
private static final Set<CorporeaIndexBlockEntity> clientIndexes = Collections.newSetFromMap(new WeakHashMap<>());

private static final Map<Pattern, IRegexStacker> patterns = new LinkedHashMap<>();
private static final Map<Pattern, IRegexStacker> PATTERNS = new LinkedHashMap<>();

/**
* (name) = Item name, or "this" for the name of the item in your hand
Expand Down Expand Up @@ -220,7 +226,7 @@ public String getName(Matcher m) {
}
});

// [a ]nice [of ](name) = 69
// [a ]nice [of ](name) = 69
addPattern("(?:a )?nice (?:of )?(.+)", new IRegexStacker() {
@Override
public int getCount(Matcher m) {
Expand Down Expand Up @@ -268,12 +274,14 @@ public CorporeaIndexBlockEntity(BlockPos pos, BlockState state) {
super(BotaniaBlockEntities.CORPOREA_INDEX, pos, state);
}

public static void commonTick(Level level, BlockPos worldPosition, BlockState state, CorporeaIndexBlockEntity self) {
public static void commonTick(Level level, BlockPos worldPosition, BlockState state,
CorporeaIndexBlockEntity self) {
double x = worldPosition.getX() + 0.5;
double y = worldPosition.getY() + 0.5;
double z = worldPosition.getZ() + 0.5;

List<Player> players = level.getEntitiesOfClass(Player.class, new AABB(x - RADIUS, y - RADIUS, z - RADIUS, x + RADIUS, y + RADIUS, z + RADIUS));
List<Player> players = level.getEntitiesOfClass(Player.class, new AABB(x - RADIUS, y - RADIUS, z - RADIUS,
x + RADIUS, y + RADIUS, z + RADIUS));
self.hasCloseby = false;
if (self.getSpark() != null) {
for (Player player : players) {
Expand Down Expand Up @@ -326,7 +334,8 @@ private CorporeaResult doRequest(CorporeaRequestMatcher matcher, int count, Corp
spark.onItemsRequested(stacks);
for (ItemStack stack : stacks) {
if (!stack.isEmpty()) {
ItemEntity item = new ItemEntity(level, worldPosition.getX() + 0.5, worldPosition.getY() + 1.5, worldPosition.getZ() + 0.5, stack);
ItemEntity item = new ItemEntity(level, worldPosition.getX() + 0.5, worldPosition.getY() + 1.5,
worldPosition.getZ() + 0.5, stack);
level.addFreshEntity(item);
}
}
Expand All @@ -340,7 +349,7 @@ private boolean isInRange(Player player) {
}

public static void addPattern(String pattern, IRegexStacker stacker) {
patterns.put(Pattern.compile(pattern), stacker);
PATTERNS.put(Pattern.compile(pattern), stacker);
}

public static int i(Matcher m, int g) {
Expand Down Expand Up @@ -378,44 +387,66 @@ public void performPlayerRequest(ServerPlayer player, CorporeaRequestMatcher req
}

public static class ClientHandler {
public static boolean onChat(Player player, String message) {
public static boolean onChat(LocalPlayer player, String message) {
if (!getNearbyValidIndexes(player).isEmpty()) {
ClientXplatAbstractions.INSTANCE.sendToServer(new IndexStringRequestPacket(message));
// TEMP TEST
var count2Matcher = getMatcherFromMsg(message, player);

ClientXplatAbstractions.INSTANCE.sendToServer(
new IndexRequestPacket(count2Matcher.second(), count2Matcher.firstInt()));
return true;
}
return false;
}

public static IntObjectPair<CorporeaRequestMatcher> getMatcherFromMsg(String message, LocalPlayer reqer) {
message = message.toLowerCase(Locale.ROOT).trim();

String name = "";
int count = 0;
boolean foundAny = false;
for (var pattern : PATTERNS.keySet()) {
// They're in the set from least -> most specific
// TODO could it be faster to iterate reversed and break once something is found?
Matcher matcher = pattern.matcher(message);
if (matcher.matches()) {
IRegexStacker stacker = PATTERNS.get(pattern);
count = Math.min(MAX_REQUEST, stacker.getCount(matcher));
name = stacker.getName(matcher).toLowerCase(Locale.ROOT).trim();
foundAny = true;
}
}

// The nonsense values above will always be filled by this point
// TODO would it make more sense for the "no special RE" matches to be special-cased?
CorporeaRequestMatcher corpyMatcher;
if (!foundAny) {
// this should never be passed?
corpyMatcher = new CorporeaConstantMatcher(false);
} else if (name.equals("this")) {
ItemStack stack = reqer.getMainHandItem();
if (!stack.isEmpty()) {
corpyMatcher = new CorporeaItemStackMatcher(stack, true);
} else {
// Well, you're gonna have a tough time checking for air
corpyMatcher = new CorporeaConstantMatcher(false);
}
} else {
corpyMatcher = new CorporeaStringMatcher(name);
}

return IntObjectPair.of(count, corpyMatcher);
}
}

public static void onChatMessage(ServerPlayer player, String message) {
public static void receiveRequestFromPlayer(ServerPlayer player, CorporeaRequestMatcher matcher, int count) {
if (player.isSpectator()) {
return;
}

List<CorporeaIndexBlockEntity> nearbyIndexes = getNearbyValidIndexes(player);
if (!nearbyIndexes.isEmpty()) {
String msg = message.toLowerCase(Locale.ROOT).trim();
for (CorporeaIndexBlockEntity index : nearbyIndexes) {
String name = "";
int count = 0;
for (Pattern pattern : patterns.keySet()) {
Matcher matcher = pattern.matcher(msg);
if (matcher.matches()) {
IRegexStacker stacker = patterns.get(pattern);
count = Math.min(MAX_REQUEST, stacker.getCount(matcher));
name = stacker.getName(matcher).toLowerCase(Locale.ROOT).trim();
}
}

if (name.equals("this")) {
ItemStack stack = player.getMainHandItem();
if (!stack.isEmpty()) {
name = stack.getHoverName().getString().toLowerCase(Locale.ROOT).trim();
}
}

index.performPlayerRequest(player, CorporeaHelper.instance().createMatcher(name), count);
}
for (CorporeaIndexBlockEntity index : nearbyIndexes) {
index.performPlayerRequest(player, matcher, count);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
package vazkii.botania.common.block.block_entity.corporea;

import com.mojang.blaze3d.vertex.PoseStack;

import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft;
import net.minecraft.client.resources.language.I18n;
Expand All @@ -21,19 +20,17 @@
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;

import org.jetbrains.annotations.Nullable;

import vazkii.botania.api.block.WandHUD;
import vazkii.botania.api.block.Wandable;
import vazkii.botania.api.corporea.*;
import vazkii.botania.api.corporea.CorporeaHelper;
import vazkii.botania.api.corporea.CorporeaRequestMatcher;
import vazkii.botania.api.corporea.CorporeaRequestor;
import vazkii.botania.api.corporea.CorporeaSpark;
import vazkii.botania.api.internal.VanillaPacketDispatcher;
import vazkii.botania.common.block.block_entity.BotaniaBlockEntities;
import vazkii.botania.common.block.block_entity.BotaniaBlockEntity;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import vazkii.botania.common.impl.corporea.CorporeaHelperImpl;

public class CorporeaRetainerBlockEntity extends BotaniaBlockEntity implements Wandable {
private static final String TAG_REQUEST_X = "requestX";
Expand All @@ -43,9 +40,6 @@ public class CorporeaRetainerBlockEntity extends BotaniaBlockEntity implements W
private static final String TAG_REQUEST_COUNT = "requestCount";
private static final String TAG_RETAIN_MISSING = "retainMissing";

private static final Map<ResourceLocation, Function<CompoundTag, ? extends CorporeaRequestMatcher>> corporeaMatcherDeserializers = new ConcurrentHashMap<>();
private static final Map<Class<? extends CorporeaRequestMatcher>, ResourceLocation> corporeaMatcherSerializers = new ConcurrentHashMap<>();

private BlockPos requestPos = BlockPos.ZERO;

@Nullable
Expand Down Expand Up @@ -103,7 +97,8 @@ public void writePacketNBT(CompoundTag cmp) {
cmp.putInt(TAG_REQUEST_Y, requestPos.getY());
cmp.putInt(TAG_REQUEST_Z, requestPos.getZ());

ResourceLocation reqType = request != null ? corporeaMatcherSerializers.get(request.getClass()) : null;
ResourceLocation reqType = request != null ?
CorporeaHelperImpl.corporeaMatcherSerializers.get(request.getClass()) : null;

if (reqType != null) {
cmp.putString(TAG_REQUEST_TYPE, reqType.toString());
Expand All @@ -123,20 +118,16 @@ public void readPacketNBT(CompoundTag cmp) {
requestPos = new BlockPos(x, y, z);

ResourceLocation reqType = ResourceLocation.tryParse(cmp.getString(TAG_REQUEST_TYPE));
if (reqType != null && corporeaMatcherDeserializers.containsKey(reqType)) {
request = corporeaMatcherDeserializers.get(reqType).apply(cmp);
if (reqType != null && CorporeaHelperImpl.corporeaMatcherDeserializers.containsKey(reqType)) {
var deser = CorporeaHelperImpl.corporeaMatcherDeserializers.get(reqType);
request = deser.nbtDeser().apply(cmp);
} else {
request = null;
}
requestCount = cmp.getInt(TAG_REQUEST_COUNT);
retainMissing = cmp.getBoolean(TAG_RETAIN_MISSING);
}

public static <T extends CorporeaRequestMatcher> void addCorporeaRequestMatcher(ResourceLocation id, Class<T> clazz, Function<CompoundTag, T> deserializer) {
corporeaMatcherSerializers.put(clazz, id);
corporeaMatcherDeserializers.put(id, deserializer);
}

public static class WandHud implements WandHUD {
private final CorporeaRetainerBlockEntity retainer;

Expand Down
Loading