diff --git a/arclight-common/build.gradle b/arclight-common/build.gradle index 3b096669..6abf5569 100644 --- a/arclight-common/build.gradle +++ b/arclight-common/build.gradle @@ -20,14 +20,14 @@ apply plugin: 'idea' apply plugin: 'io.izzel.arclight' ext { - minecraftVersion = '1.16.3' - forgeVersion = '34.1.25' + minecraftVersion = '1.16.4' + forgeVersion = '35.1.0' } arclight { mcVersion = minecraftVersion forgeVersion = project.ext.forgeVersion - bukkitVersion = 'v1_16_R2' + bukkitVersion = 'v1_16_R3' wipeVersion = true reobfVersion = false accessTransformer = project.file('bukkit.at') diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/entity/player/ServerPlayerEntityBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/entity/player/ServerPlayerEntityBridge.java index 03de9e9d..7535d5c3 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/entity/player/ServerPlayerEntityBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/entity/player/ServerPlayerEntityBridge.java @@ -9,6 +9,7 @@ import org.bukkit.craftbukkit.v.entity.CraftPlayer; import org.bukkit.event.player.PlayerTeleportEvent; import java.util.Optional; +import java.util.UUID; public interface ServerPlayerEntityBridge extends PlayerEntityBridge { @@ -25,9 +26,9 @@ public interface ServerPlayerEntityBridge extends PlayerEntityBridge { void bridge$setCompassTarget(Location location); - void bridge$sendMessage(ITextComponent[] ichatbasecomponent); + void bridge$sendMessage(ITextComponent[] ichatbasecomponent, UUID uuid); - void bridge$sendMessage(ITextComponent component); + void bridge$sendMessage(ITextComponent component, UUID uuid); boolean bridge$isJoining(); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/world/chunk/ChunkBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/world/chunk/ChunkBridge.java index 991d8000..1be8e521 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/world/chunk/ChunkBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/world/chunk/ChunkBridge.java @@ -3,6 +3,7 @@ package io.izzel.arclight.common.bridge.world.chunk; import net.minecraft.block.BlockState; import net.minecraft.util.math.BlockPos; import org.bukkit.Chunk; +import org.bukkit.craftbukkit.v.persistence.CraftPersistentDataContainer; public interface ChunkBridge { @@ -21,4 +22,6 @@ public interface ChunkBridge { void bridge$loadCallback(); void bridge$unloadCallback(); + + CraftPersistentDataContainer bridge$getPersistentContainer(); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/player/ServerPlayerEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/player/ServerPlayerEntityMixin.java index 80254969..08ca09fc 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/player/ServerPlayerEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/entity/player/ServerPlayerEntityMixin.java @@ -720,20 +720,20 @@ public abstract class ServerPlayerEntityMixin extends PlayerEntityMixin implemen this.lastExperience = -1; } - public void sendMessage(ITextComponent[] components) { + public void sendMessage(UUID uuid, ITextComponent[] components) { for (final ITextComponent component : components) { - this.sendMessage(component, Util.DUMMY_UUID); + this.sendMessage(component, uuid == null ? Util.DUMMY_UUID : uuid); } } @Override - public void bridge$sendMessage(ITextComponent[] components) { - sendMessage(components); + public void bridge$sendMessage(ITextComponent[] components, UUID uuid) { + sendMessage(uuid, components); } @Override - public void bridge$sendMessage(ITextComponent component) { - this.sendMessage(component, Util.DUMMY_UUID); + public void bridge$sendMessage(ITextComponent component, UUID uuid) { + this.sendMessage(component, uuid == null ? Util.DUMMY_UUID : uuid); } @Inject(method = "setGameType", cancellable = true, at = @At("HEAD")) diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/login/ServerLoginNetHandlerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/login/ServerLoginNetHandlerMixin.java index 4a78c620..58917483 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/login/ServerLoginNetHandlerMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/login/ServerLoginNetHandlerMixin.java @@ -17,6 +17,7 @@ import net.minecraft.network.login.server.SEnableCompressionPacket; import net.minecraft.network.login.server.SEncryptionRequestPacket; import net.minecraft.network.login.server.SLoginSuccessPacket; import net.minecraft.server.MinecraftServer; +import net.minecraft.util.CryptException; import net.minecraft.util.CryptManager; import net.minecraft.util.DefaultUncaughtExceptionHandler; import net.minecraft.util.text.ITextComponent; @@ -36,6 +37,7 @@ import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import javax.annotation.Nullable; +import javax.crypto.Cipher; import javax.crypto.SecretKey; import java.math.BigInteger; import java.net.InetAddress; @@ -131,7 +133,7 @@ public abstract class ServerLoginNetHandlerMixin implements ServerLoginNetHandle this.loginGameProfile = packetIn.getProfile(); if (this.server.isServerInOnlineMode() && !this.networkManager.isLocalChannel()) { this.currentLoginState = ServerLoginNetHandler.State.KEY; - this.networkManager.sendPacket(new SEncryptionRequestPacket("", this.server.getKeyPair().getPublic(), this.verifyToken)); + this.networkManager.sendPacket(new SEncryptionRequestPacket("", this.server.getKeyPair().getPublic().getEncoded(), this.verifyToken)); } else { class Handler extends Thread { @@ -180,60 +182,69 @@ public abstract class ServerLoginNetHandlerMixin implements ServerLoginNetHandle public void processEncryptionResponse(CEncryptionResponsePacket packetIn) { Validate.validState(this.currentLoginState == ServerLoginNetHandler.State.KEY, "Unexpected key packet"); PrivateKey privatekey = this.server.getKeyPair().getPrivate(); - if (!Arrays.equals(this.verifyToken, packetIn.getVerifyToken(privatekey))) { - throw new IllegalStateException("Invalid nonce!"); - } else { - this.secretKey = packetIn.getSecretKey(privatekey); - this.currentLoginState = ServerLoginNetHandler.State.AUTHENTICATING; - this.networkManager.enableEncryption(this.secretKey); - class Handler extends Thread { - Handler() { - super(SidedThreadGroups.SERVER, "User Authenticator #" + AUTHENTICATOR_THREAD_ID.incrementAndGet()); - } - - public void run() { - GameProfile gameprofile = loginGameProfile; - - try { - String s = (new BigInteger(CryptManager.getServerIdHash("", server.getKeyPair().getPublic(), secretKey))).toString(16); - loginGameProfile = server.getMinecraftSessionService().hasJoinedServer(new GameProfile(null, gameprofile.getName()), s, this.getAddress()); - if (loginGameProfile != null) { - if (!networkManager.isChannelOpen()) { - return; - } - arclight$preLogin(); - } else if (server.isSinglePlayer()) { - LOGGER.warn("Failed to verify username but will let them in anyway!"); - loginGameProfile = getOfflineProfile(gameprofile); - currentLoginState = ServerLoginNetHandler.State.NEGOTIATING; - } else { - disconnect(new TranslationTextComponent("multiplayer.disconnect.unverified_username")); - LOGGER.error("Username '{}' tried to join with an invalid session", gameprofile.getName()); - } - } catch (Exception var3) { - if (server.isSinglePlayer()) { - LOGGER.warn("Authentication servers are down but will let them in anyway!"); - loginGameProfile = getOfflineProfile(gameprofile); - currentLoginState = ServerLoginNetHandler.State.NEGOTIATING; - } else { - disconnect(new TranslationTextComponent("multiplayer.disconnect.authservers_down")); - LOGGER.error("Couldn't verify username because servers are unavailable"); - } - } - - } - - @Nullable - private InetAddress getAddress() { - SocketAddress socketaddress = networkManager.getRemoteAddress(); - return server.getPreventProxyConnections() && socketaddress instanceof InetSocketAddress ? ((InetSocketAddress) socketaddress).getAddress() : null; - } + final String s; + try { + if (!Arrays.equals(this.verifyToken, packetIn.getVerifyToken(privatekey))) { + throw new IllegalStateException("Protocol error"); } - Thread thread = new Handler(); - thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(LOGGER)); - thread.start(); + + this.secretKey = packetIn.getSecretKey(privatekey); + Cipher cipher = CryptManager.createNetCipherInstance(2, this.secretKey); + Cipher cipher1 = CryptManager.createNetCipherInstance(1, this.secretKey); + s = (new BigInteger(CryptManager.getServerIdHash("", this.server.getKeyPair().getPublic(), this.secretKey))).toString(16); + this.currentLoginState = ServerLoginNetHandler.State.AUTHENTICATING; + this.networkManager.func_244777_a(cipher, cipher1); + } catch (CryptException cryptexception) { + throw new IllegalStateException("Protocol error", cryptexception); } + + class Handler extends Thread { + + Handler() { + super(SidedThreadGroups.SERVER, "User Authenticator #" + AUTHENTICATOR_THREAD_ID.incrementAndGet()); + } + + public void run() { + GameProfile gameprofile = loginGameProfile; + + try { + loginGameProfile = server.getMinecraftSessionService().hasJoinedServer(new GameProfile(null, gameprofile.getName()), s, this.getAddress()); + if (loginGameProfile != null) { + if (!networkManager.isChannelOpen()) { + return; + } + arclight$preLogin(); + } else if (server.isSinglePlayer()) { + LOGGER.warn("Failed to verify username but will let them in anyway!"); + loginGameProfile = getOfflineProfile(gameprofile); + currentLoginState = ServerLoginNetHandler.State.NEGOTIATING; + } else { + disconnect(new TranslationTextComponent("multiplayer.disconnect.unverified_username")); + LOGGER.error("Username '{}' tried to join with an invalid session", gameprofile.getName()); + } + } catch (Exception var3) { + if (server.isSinglePlayer()) { + LOGGER.warn("Authentication servers are down but will let them in anyway!"); + loginGameProfile = getOfflineProfile(gameprofile); + currentLoginState = ServerLoginNetHandler.State.NEGOTIATING; + } else { + disconnect(new TranslationTextComponent("multiplayer.disconnect.authservers_down")); + LOGGER.error("Couldn't verify username because servers are unavailable"); + } + } + + } + + @Nullable + private InetAddress getAddress() { + SocketAddress socketaddress = networkManager.getRemoteAddress(); + return server.getPreventProxyConnections() && socketaddress instanceof InetSocketAddress ? ((InetSocketAddress) socketaddress).getAddress() : null; + } + } + Thread thread = new Handler(); + thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(LOGGER)); + thread.start(); } private void arclight$preLogin() throws Exception { diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/play/ServerPlayNetHandlerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/play/ServerPlayNetHandlerMixin.java index 16166786..414a4ca2 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/play/ServerPlayNetHandlerMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/play/ServerPlayNetHandlerMixin.java @@ -29,14 +29,12 @@ import net.minecraft.entity.player.ChatVisibility; import net.minecraft.entity.player.PlayerInventory; import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.entity.projectile.AbstractArrowEntity; -import net.minecraft.inventory.EquipmentSlotType; import net.minecraft.inventory.container.Container; import net.minecraft.inventory.container.MerchantContainer; import net.minecraft.inventory.container.Slot; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.item.Items; -import net.minecraft.item.WritableBookItem; import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.ListNBT; import net.minecraft.nbt.StringNBT; @@ -143,6 +141,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import java.util.Collections; +import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.Set; @@ -409,47 +408,57 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB CraftEventFactory.callTradeSelectEvent(this.player, i, (MerchantContainer) container); } - /** - * @author IzzelAliz - * @reason - */ - @Overwrite - public void processEditBook(CEditBookPacket packetplayinbedit) { - PacketThreadUtil.checkThreadAndEnqueue(packetplayinbedit, (ServerPlayNetHandler) (Object) this, this.player.getServerWorld()); - if (lastBookTick == 0) lastBookTick = ArclightConstants.currentTick; + @Inject(method = "processEditBook", cancellable = true, at = @At("HEAD")) + private void arclight$editBookSpam(CEditBookPacket packetIn, CallbackInfo ci) { if (this.lastBookTick + 20 > ArclightConstants.currentTick) { this.disconnect("Book edited too quickly!"); return; } this.lastBookTick = ArclightConstants.currentTick; - EquipmentSlotType enumitemslot = (packetplayinbedit.getHand() == Hand.MAIN_HAND) ? EquipmentSlotType.MAINHAND : EquipmentSlotType.OFFHAND; - ItemStack itemstack = packetplayinbedit.getStack(); - if (!itemstack.isEmpty() && WritableBookItem.isNBTValid(itemstack.getTag())) { - ItemStack itemstack2 = this.player.getHeldItem(packetplayinbedit.getHand()); - if (itemstack.getItem() == Items.WRITABLE_BOOK && itemstack2.getItem() == Items.WRITABLE_BOOK) { - if (packetplayinbedit.shouldUpdateAll()) { - ItemStack itemstack3 = new ItemStack(Items.WRITTEN_BOOK); - CompoundNBT nbttagcompound = itemstack2.getTag(); - if (nbttagcompound != null) { - itemstack3.setTag(nbttagcompound.copy()); - } - itemstack3.setTagInfo("author", StringNBT.valueOf(this.player.getName().getString())); - itemstack3.setTagInfo("title", StringNBT.valueOf(itemstack.getTag().getString("title"))); - ListNBT nbttaglist = itemstack.getTag().getList("pages", 8); - for (int i = 0; i < nbttaglist.size(); ++i) { - String s = nbttaglist.getString(i); - StringTextComponent chatcomponenttext = new StringTextComponent(s); - s = ITextComponent.Serializer.toJson(chatcomponenttext); - nbttaglist.set(i, StringNBT.valueOf(s)); - } - itemstack3.setTagInfo("pages", nbttaglist); - this.player.setHeldItem(packetplayinbedit.getHand(), CraftEventFactory.handleEditBookEvent(this.player, enumitemslot, itemstack2, itemstack3)); - } else { - ItemStack old = itemstack2.copy(); - itemstack2.setTagInfo("pages", itemstack.getTag().getList("pages", 8)); - CraftEventFactory.handleEditBookEvent(this.player, enumitemslot, old, itemstack2); - } + } + + /** + * @author IzzelAliz + * @reason + */ + @Overwrite + private void func_244536_a(List p_244536_1_, int p_244536_2_) { + ItemStack itemstack = this.player.inventory.getStackInSlot(p_244536_2_); + if (itemstack.getItem() == Items.WRITABLE_BOOK) { + ListNBT listnbt = new ListNBT(); + p_244536_1_.stream().map(StringNBT::valueOf).forEach(listnbt::add); + ItemStack old = itemstack.copy(); + itemstack.setTagInfo("pages", listnbt); + CraftEventFactory.handleEditBookEvent(player, p_244536_2_, old, itemstack); + } + } + + /** + * @author IzzelAliz + * @reason + */ + @Overwrite + private void func_244534_a(String p_244534_1_, List p_244534_2_, int p_244534_3_) { + ItemStack itemstack = this.player.inventory.getStackInSlot(p_244534_3_); + if (itemstack.getItem() == Items.WRITABLE_BOOK) { + ItemStack itemstack1 = new ItemStack(Items.WRITTEN_BOOK); + CompoundNBT compoundnbt = itemstack.getTag(); + if (compoundnbt != null) { + itemstack1.setTag(compoundnbt.copy()); } + + itemstack1.setTagInfo("author", StringNBT.valueOf(this.player.getName().getString())); + itemstack1.setTagInfo("title", StringNBT.valueOf(p_244534_1_)); + ListNBT listnbt = new ListNBT(); + + for (String s : p_244534_2_) { + ITextComponent itextcomponent = new StringTextComponent(s); + String s1 = ITextComponent.Serializer.toJson(itextcomponent); + listnbt.add(StringNBT.valueOf(s1)); + } + + itemstack1.setTagInfo("pages", listnbt); + this.player.inventory.setInventorySlotContents(p_244534_3_, CraftEventFactory.handleEditBookEvent(player, p_244534_3_, itemstack, itemstack1)); } } @@ -949,11 +958,11 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB if (!async && s.startsWith("/")) { this.handleSlashCommand(s); } else if (this.player.getChatVisibility() != ChatVisibility.SYSTEM) { - Player player = this.getPlayer(); - AsyncPlayerChatEvent event = new AsyncPlayerChatEvent(async, player, s, new LazyPlayerSet(this.minecraftServer)); + Player thisPlayer = this.getPlayer(); + AsyncPlayerChatEvent event = new AsyncPlayerChatEvent(async, thisPlayer, s, new LazyPlayerSet(this.minecraftServer)); this.server.getPluginManager().callEvent(event); if (PlayerChatEvent.getHandlerList().getRegisteredListeners().length != 0) { - PlayerChatEvent queueEvent = new PlayerChatEvent(player, event.getMessage(), event.getFormat(), event.getRecipients()); + PlayerChatEvent queueEvent = new PlayerChatEvent(thisPlayer, event.getMessage(), event.getFormat(), event.getRecipients()); queueEvent.setCancelled(event.isCancelled()); class SyncChat extends Waitable { @@ -969,11 +978,11 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB Bukkit.getConsoleSender().sendMessage(CraftChatMessage.fromComponent(component)); if (((LazyPlayerSet) queueEvent.getRecipients()).isLazy()) { for (ServerPlayerEntity player : minecraftServer.getPlayerList().players) { - ((ServerPlayerEntityBridge) player).bridge$sendMessage(component); + ((ServerPlayerEntityBridge) player).bridge$sendMessage(component, thisPlayer.getUniqueId()); } } else { for (Player player2 : queueEvent.getRecipients()) { - ((ServerPlayerEntityBridge) ((CraftPlayer) player2).getHandle()).bridge$sendMessage(component); + ((ServerPlayerEntityBridge) ((CraftPlayer) player2).getHandle()).bridge$sendMessage(component, thisPlayer.getUniqueId()); } } return null; @@ -1010,11 +1019,11 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB Bukkit.getConsoleSender().sendMessage(CraftChatMessage.fromComponent(component)); if (((LazyPlayerSet) event.getRecipients()).isLazy()) { for (ServerPlayerEntity recipient : minecraftServer.getPlayerList().players) { - ((ServerPlayerEntityBridge) recipient).bridge$sendMessage(component); + ((ServerPlayerEntityBridge) recipient).bridge$sendMessage(component, thisPlayer.getUniqueId()); } } else { for (Player recipient2 : event.getRecipients()) { - ((ServerPlayerEntityBridge) ((CraftPlayer) recipient2).getHandle()).bridge$sendMessage(component); + ((ServerPlayerEntityBridge) ((CraftPlayer) recipient2).getHandle()).bridge$sendMessage(component, thisPlayer.getUniqueId()); } } return null; @@ -1597,8 +1606,8 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB } } - @Inject(method = "processUpdateSign", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/ServerPlayerEntity;markPlayerActive()V")) - private void arclight$noSignEdit(CUpdateSignPacket packetIn, CallbackInfo ci) { + @Inject(method = "func_244542_a", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/ServerPlayerEntity;markPlayerActive()V")) + private void arclight$noSignEdit(CUpdateSignPacket p_244542_1_, List p_244542_2_, CallbackInfo ci) { if (((ServerPlayerEntityBridge) player).bridge$isMovementBlocked()) { ci.cancel(); } @@ -1606,11 +1615,11 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB private ITextComponent[] arclight$lines; - @Inject(method = "processUpdateSign", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/network/play/client/CUpdateSignPacket;getLines()[Ljava/lang/String;")) - public void arclight$onSignChangePre(CUpdateSignPacket packetIn, CallbackInfo ci) { - String[] lines = packetIn.getLines(); + @Inject(method = "func_244542_a", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/tileentity/SignTileEntity;getIsEditable()Z")) + public void arclight$onSignChangePre(CUpdateSignPacket p_244542_1_, List p_244542_2_, CallbackInfo ci) { + String[] lines = p_244542_2_.toArray(new String[0]); Player player = ((CraftServer) Bukkit.getServer()).getPlayer(this.player); - CraftBlock block = CraftBlock.at(this.player.world, packetIn.getPosition()); + CraftBlock block = CraftBlock.at(this.player.world, p_244542_1_.getPosition()); String[] bukkitLines = new String[lines.length]; for (int i = 0; i < lines.length; i++) { bukkitLines[i] = TextFormatting.getTextWithoutFormattingCodes( @@ -1630,7 +1639,7 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB } } - @Redirect(method = "processUpdateSign", at = @At(value = "INVOKE", target = "Lnet/minecraft/tileentity/SignTileEntity;setText(ILnet/minecraft/util/text/ITextComponent;)V")) + @Redirect(method = "func_244542_a", at = @At(value = "INVOKE", target = "Lnet/minecraft/tileentity/SignTileEntity;setText(ILnet/minecraft/util/text/ITextComponent;)V")) public void arclight$onSignChangePost(SignTileEntity signTileEntity, int line, ITextComponent signText) { if (arclight$lines != null) { signTileEntity.setText(line, arclight$lines[line]); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/management/PlayerListMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/management/PlayerListMixin.java index 3cf03118..6d6d27d0 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/management/PlayerListMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/management/PlayerListMixin.java @@ -183,7 +183,9 @@ public abstract class PlayerListMixin implements PlayerListBridge { @Inject(method = "playerLoggedOut", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/management/PlayerList;writePlayerData(Lnet/minecraft/entity/player/ServerPlayerEntity;)V")) private void arclight$playerQuitPre(ServerPlayerEntity playerIn, CallbackInfo ci) { - ((ServerPlayerEntityBridge) playerIn).bridge$getBukkitEntity().closeInventory(); + if (playerIn.container != playerIn.openContainer) { + ((ServerPlayerEntityBridge) playerIn).bridge$getBukkitEntity().closeInventory(); + } PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(playerIn), "\u00A7e" + playerIn.getScoreboardName() + " left the game"); cserver.getPluginManager().callEvent(playerQuitEvent); ((ServerPlayerEntityBridge) playerIn).bridge$getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/TeleporterMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/TeleporterMixin.java index fe20552e..730c18de 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/TeleporterMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/TeleporterMixin.java @@ -80,7 +80,7 @@ public abstract class TeleporterMixin implements TeleporterBridge { } @SuppressWarnings({"unchecked", "rawtypes"}) - @Inject(method = "makePortal", at = @At("RETURN")) + @Inject(method = "makePortal", cancellable = true, at = @At("RETURN")) private void arclight$portalCreate(BlockPos pos, Direction.Axis axis, CallbackInfoReturnable> cir) { CraftWorld craftWorld = ((WorldBridge) this.world).bridge$getWorld(); List blockStates; @@ -92,7 +92,11 @@ public abstract class TeleporterMixin implements TeleporterBridge { PortalCreateEvent event = new PortalCreateEvent(blockStates, craftWorld, (this.arclight$entity == null) ? null : ((EntityBridge) this.arclight$entity).bridge$getBukkitEntity(), PortalCreateEvent.CreateReason.NETHER_PAIR); Bukkit.getPluginManager().callEvent(event); - if (!event.isCancelled() && this.arclight$populator != null) { + if (event.isCancelled()) { + cir.setReturnValue(Optional.empty()); + return; + } + if (this.arclight$populator != null) { this.arclight$populator.updateList(); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/chunk/ChunkMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/chunk/ChunkMixin.java index 15189a3d..7b825759 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/chunk/ChunkMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/chunk/ChunkMixin.java @@ -17,6 +17,8 @@ import net.minecraft.world.chunk.ChunkSection; import net.minecraft.world.server.ServerWorld; import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v.CraftChunk; +import org.bukkit.craftbukkit.v.persistence.CraftPersistentDataContainer; +import org.bukkit.craftbukkit.v.persistence.CraftPersistentDataTypeRegistry; import org.bukkit.event.world.ChunkLoadEvent; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -48,6 +50,9 @@ public abstract class ChunkMixin implements ChunkBridge { private transient boolean arclight$doPlace; public ServerWorld $$world; + private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry(); + public final CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY); + @Inject(method = "(Lnet/minecraft/world/World;Lnet/minecraft/util/math/ChunkPos;Lnet/minecraft/world/biome/BiomeContainer;Lnet/minecraft/util/palette/UpgradeData;Lnet/minecraft/world/ITickList;Lnet/minecraft/world/ITickList;J[Lnet/minecraft/world/chunk/ChunkSection;Ljava/util/function/Consumer;)V", at = @At("RETURN")) private void arclight$init(World worldIn, ChunkPos chunkPosIn, BiomeContainer biomeContainerIn, UpgradeData upgradeDataIn, ITickList tickBlocksIn, ITickList tickFluidsIn, long inhabitedTimeIn, ChunkSection[] sectionsIn, Consumer postLoadConsumerIn, CallbackInfo ci) { this.$$world = ((ServerWorld) worldIn); @@ -63,6 +68,11 @@ public abstract class ChunkMixin implements ChunkBridge { return bukkitChunk; } + @Override + public CraftPersistentDataContainer bridge$getPersistentContainer() { + return this.persistentDataContainer; + } + @Override public void bridge$setBukkitChunk(org.bukkit.Chunk chunk) { this.bukkitChunk = chunk; diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/event/ArclightEventDispatcherRegistry.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/event/ArclightEventDispatcherRegistry.java index 98ab5165..3f8dd6af 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/event/ArclightEventDispatcherRegistry.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/event/ArclightEventDispatcherRegistry.java @@ -13,6 +13,7 @@ public abstract class ArclightEventDispatcherRegistry { MinecraftForge.EVENT_BUS.register(new EntityTeleportEventDispatcher()); MinecraftForge.EVENT_BUS.register(new ItemEntityEventDispatcher()); MinecraftForge.EVENT_BUS.register(new WorldEventDispatcher()); + MinecraftForge.EVENT_BUS.register(new ChunkEventHandler()); ArclightMod.LOGGER.info("registry.forge-event"); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/event/ChunkEventHandler.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/event/ChunkEventHandler.java new file mode 100644 index 00000000..d82f8dca --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/event/ChunkEventHandler.java @@ -0,0 +1,36 @@ +package io.izzel.arclight.common.mod.server.event; + +import io.izzel.arclight.common.bridge.world.chunk.ChunkBridge; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.INBT; +import net.minecraft.world.chunk.ChunkStatus; +import net.minecraft.world.chunk.IChunk; +import net.minecraftforge.event.world.ChunkDataEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import org.bukkit.craftbukkit.v.persistence.CraftPersistentDataContainer; + +public class ChunkEventHandler { + + @SubscribeEvent + public void onChunkLoad(ChunkDataEvent.Load event) { + if (event.getStatus() == ChunkStatus.Type.LEVELCHUNK) { + IChunk chunk = event.getChunk(); + CompoundNBT nbt = event.getData(); + INBT values = nbt.get("ChunkBukkitValues"); + if (values instanceof CompoundNBT) { + ((ChunkBridge) chunk).bridge$getPersistentContainer().putAll((CompoundNBT) values); + } + } + } + + @SubscribeEvent + public void onChunkSave(ChunkDataEvent.Save event) { + IChunk chunk = event.getChunk(); + if (chunk instanceof ChunkBridge) { + CraftPersistentDataContainer container = ((ChunkBridge) chunk).bridge$getPersistentContainer(); + if (!container.isEmpty()) { + event.getData().put("ChunkBukkitValues", container.toTagCompound()); + } + } + } +} diff --git a/arclight-forge-1.16/build.gradle b/arclight-forge-1.16/build.gradle index 59bde771..8faece32 100644 --- a/arclight-forge-1.16/build.gradle +++ b/arclight-forge-1.16/build.gradle @@ -21,14 +21,14 @@ apply plugin: 'io.izzel.arclight' apply plugin: 'maven-publish' ext { - minecraftVersion = '1.16.3' - forgeVersion = '34.1.25' + minecraftVersion = '1.16.4' + forgeVersion = '35.1.0' } arclight { mcVersion = minecraftVersion forgeVersion = project.ext.forgeVersion - bukkitVersion = 'v1_16_R2' + bukkitVersion = 'v1_16_R3' wipeVersion = true reobfVersion = true accessTransformer = project(':arclight-common').file('bukkit.at')