diff --git a/README.md b/README.md index 927ce912..af456be6 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ A faction's power cap increases as new members join, expanding their ability to   -### **GET STARTED** +### **GET STARTED** Factions Mod is very intuitive and works immediately after installation, requiring no additional configuration. However, you can read further about the mod on the [Wiki][wiki]. Our wiki goes in depth about the factions mechanics, its configuration, commands and integrations. diff --git a/src/main/java/io/icker/factions/core/WorldManager.java b/src/main/java/io/icker/factions/core/WorldManager.java index c6067645..fbbdb620 100644 --- a/src/main/java/io/icker/factions/core/WorldManager.java +++ b/src/main/java/io/icker/factions/core/WorldManager.java @@ -29,7 +29,7 @@ private static void onMove(ServerPlayer player) { ServerLevel world = (ServerLevel) player.level(); String dimension = world.dimension().identifier().toString(); - ChunkPos chunkPos = world.getChunk(player.blockPosition()).getPos(); + ChunkPos chunkPos = player.chunkPosition(); Claim claim = Claim.get(chunkPos.x(), chunkPos.z(), dimension); if (user.autoclaim && claim == null) { diff --git a/src/main/java/io/icker/factions/database/SerializerRegistry.java b/src/main/java/io/icker/factions/database/SerializerRegistry.java index c5d50ddf..b121f70e 100644 --- a/src/main/java/io/icker/factions/database/SerializerRegistry.java +++ b/src/main/java/io/icker/factions/database/SerializerRegistry.java @@ -11,6 +11,7 @@ import io.icker.factions.api.persistents.User.SoundMode; import io.icker.factions.util.WorldUtils; +import net.minecraft.core.RegistryAccess; import net.minecraft.core.UUIDUtil; import net.minecraft.nbt.ByteArrayTag; import net.minecraft.nbt.ByteTag; @@ -146,6 +147,17 @@ private static > Serializer createEnumSerializer el -> Enum.valueOf(clazz, el.asString().orElse(""))); } + private static RegistryAccess resolveRegistryAccess() { + var world = WorldUtils.getWorld("minecraft:overworld"); + if (world != null) { + return world.registryAccess(); + } + if (WorldUtils.server != null) { + return WorldUtils.server.registryAccess(); + } + return null; + } + public record InventoryItem(int slot, ItemStack stack) { public static final Codec CODEC = RecordCodecBuilder.create( @@ -165,12 +177,16 @@ public record InventoryItem(int slot, ItemStack stack) { private static Serializer createInventorySerializer(int size) { return new Serializer( val -> { + RegistryAccess registryAccess = resolveRegistryAccess(); + if (registryAccess == null) { + FactionsMod.LOGGER.error( + "Registry access unavailable; skipping inventory serialization."); + return new ListTag(); + } ProblemReporter.ScopedCollector reporter = new ProblemReporter.ScopedCollector(FactionsMod.LOGGER); TagValueOutput view = - TagValueOutput.createWithContext( - reporter, - WorldUtils.getWorld("minecraft:overworld").registryAccess()); + TagValueOutput.createWithContext(reporter, registryAccess); TypedOutputList appender = view.list("Data", InventoryItem.CODEC); @@ -186,6 +202,17 @@ private static Serializer createInventorySerializer(in return view.buildResult().getList("Data").get(); }, el -> { + RegistryAccess registryAccess = resolveRegistryAccess(); + SimpleContainer inventory = new SimpleContainer(size); + for (int i = 0; i < size; ++i) { + inventory.setItem(i, ItemStack.EMPTY); + } + if (registryAccess == null) { + FactionsMod.LOGGER.error( + "Registry access unavailable; skipping inventory deserialization."); + return inventory; + } + CompoundTag compound = new CompoundTag(); compound.put("Data", el); @@ -193,16 +220,7 @@ private static Serializer createInventorySerializer(in new ProblemReporter.ScopedCollector(FactionsMod.LOGGER); ValueInput view = - TagValueInput.create( - reporter, - WorldUtils.getWorld("minecraft:overworld").registryAccess(), - compound); - - SimpleContainer inventory = new SimpleContainer(size); - - for (int i = 0; i < size; ++i) { - inventory.setItem(i, ItemStack.EMPTY); - } + TagValueInput.create(reporter, registryAccess, compound); TypedInputList list_view = view.listOrEmpty("Data", InventoryItem.CODEC); diff --git a/src/main/java/io/icker/factions/mixin/ServerGamePacketListenerImplMixin.java b/src/main/java/io/icker/factions/mixin/ServerGamePacketListenerImplMixin.java index 89b6705c..c5bef8b4 100644 --- a/src/main/java/io/icker/factions/mixin/ServerGamePacketListenerImplMixin.java +++ b/src/main/java/io/icker/factions/mixin/ServerGamePacketListenerImplMixin.java @@ -21,9 +21,19 @@ public class ServerGamePacketListenerImplMixin { @Shadow public ServerPlayer player; - @Inject(method = "handleMovePlayer", at = @At("HEAD")) + @Inject(method = "handleMovePlayer", at = @At("TAIL")) public void handleMovePlayer(ServerboundMovePlayerPacket packet, CallbackInfo ci) { - PlayerEvents.ON_MOVE.invoker().onMove(player); + if (player == null) return; + if (player.level() == null) return; + + var server = player.level().getServer(); + if (server == null) return; + + if (server.isSameThread()) { + PlayerEvents.ON_MOVE.invoker().onMove(player); + } else { + server.execute(() -> PlayerEvents.ON_MOVE.invoker().onMove(player)); + } } @Inject(method = "broadcastChatMessage", at = @At("HEAD"), cancellable = true)