1.16.4 update

This commit is contained in:
IzzelAliz 2020-11-21 12:17:26 +08:00
parent 3caea5943c
commit 9d06987a13
12 changed files with 197 additions and 120 deletions

View File

@ -20,14 +20,14 @@ apply plugin: 'idea'
apply plugin: 'io.izzel.arclight' apply plugin: 'io.izzel.arclight'
ext { ext {
minecraftVersion = '1.16.3' minecraftVersion = '1.16.4'
forgeVersion = '34.1.25' forgeVersion = '35.1.0'
} }
arclight { arclight {
mcVersion = minecraftVersion mcVersion = minecraftVersion
forgeVersion = project.ext.forgeVersion forgeVersion = project.ext.forgeVersion
bukkitVersion = 'v1_16_R2' bukkitVersion = 'v1_16_R3'
wipeVersion = true wipeVersion = true
reobfVersion = false reobfVersion = false
accessTransformer = project.file('bukkit.at') accessTransformer = project.file('bukkit.at')

View File

@ -9,6 +9,7 @@ import org.bukkit.craftbukkit.v.entity.CraftPlayer;
import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.event.player.PlayerTeleportEvent;
import java.util.Optional; import java.util.Optional;
import java.util.UUID;
public interface ServerPlayerEntityBridge extends PlayerEntityBridge { public interface ServerPlayerEntityBridge extends PlayerEntityBridge {
@ -25,9 +26,9 @@ public interface ServerPlayerEntityBridge extends PlayerEntityBridge {
void bridge$setCompassTarget(Location location); 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(); boolean bridge$isJoining();

View File

@ -3,6 +3,7 @@ package io.izzel.arclight.common.bridge.world.chunk;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import org.bukkit.Chunk; import org.bukkit.Chunk;
import org.bukkit.craftbukkit.v.persistence.CraftPersistentDataContainer;
public interface ChunkBridge { public interface ChunkBridge {
@ -21,4 +22,6 @@ public interface ChunkBridge {
void bridge$loadCallback(); void bridge$loadCallback();
void bridge$unloadCallback(); void bridge$unloadCallback();
CraftPersistentDataContainer bridge$getPersistentContainer();
} }

View File

@ -720,20 +720,20 @@ public abstract class ServerPlayerEntityMixin extends PlayerEntityMixin implemen
this.lastExperience = -1; this.lastExperience = -1;
} }
public void sendMessage(ITextComponent[] components) { public void sendMessage(UUID uuid, ITextComponent[] components) {
for (final ITextComponent component : components) { for (final ITextComponent component : components) {
this.sendMessage(component, Util.DUMMY_UUID); this.sendMessage(component, uuid == null ? Util.DUMMY_UUID : uuid);
} }
} }
@Override @Override
public void bridge$sendMessage(ITextComponent[] components) { public void bridge$sendMessage(ITextComponent[] components, UUID uuid) {
sendMessage(components); sendMessage(uuid, components);
} }
@Override @Override
public void bridge$sendMessage(ITextComponent component) { public void bridge$sendMessage(ITextComponent component, UUID uuid) {
this.sendMessage(component, Util.DUMMY_UUID); this.sendMessage(component, uuid == null ? Util.DUMMY_UUID : uuid);
} }
@Inject(method = "setGameType", cancellable = true, at = @At("HEAD")) @Inject(method = "setGameType", cancellable = true, at = @At("HEAD"))

View File

@ -17,6 +17,7 @@ import net.minecraft.network.login.server.SEnableCompressionPacket;
import net.minecraft.network.login.server.SEncryptionRequestPacket; import net.minecraft.network.login.server.SEncryptionRequestPacket;
import net.minecraft.network.login.server.SLoginSuccessPacket; import net.minecraft.network.login.server.SLoginSuccessPacket;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.util.CryptException;
import net.minecraft.util.CryptManager; import net.minecraft.util.CryptManager;
import net.minecraft.util.DefaultUncaughtExceptionHandler; import net.minecraft.util.DefaultUncaughtExceptionHandler;
import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.ITextComponent;
@ -36,6 +37,7 @@ import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import javax.crypto.Cipher;
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
import java.math.BigInteger; import java.math.BigInteger;
import java.net.InetAddress; import java.net.InetAddress;
@ -131,7 +133,7 @@ public abstract class ServerLoginNetHandlerMixin implements ServerLoginNetHandle
this.loginGameProfile = packetIn.getProfile(); this.loginGameProfile = packetIn.getProfile();
if (this.server.isServerInOnlineMode() && !this.networkManager.isLocalChannel()) { if (this.server.isServerInOnlineMode() && !this.networkManager.isLocalChannel()) {
this.currentLoginState = ServerLoginNetHandler.State.KEY; 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 { } else {
class Handler extends Thread { class Handler extends Thread {
@ -180,60 +182,69 @@ public abstract class ServerLoginNetHandlerMixin implements ServerLoginNetHandle
public void processEncryptionResponse(CEncryptionResponsePacket packetIn) { public void processEncryptionResponse(CEncryptionResponsePacket packetIn) {
Validate.validState(this.currentLoginState == ServerLoginNetHandler.State.KEY, "Unexpected key packet"); Validate.validState(this.currentLoginState == ServerLoginNetHandler.State.KEY, "Unexpected key packet");
PrivateKey privatekey = this.server.getKeyPair().getPrivate(); 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() { final String s;
super(SidedThreadGroups.SERVER, "User Authenticator #" + AUTHENTICATOR_THREAD_ID.incrementAndGet()); try {
} if (!Arrays.equals(this.verifyToken, packetIn.getVerifyToken(privatekey))) {
throw new IllegalStateException("Protocol error");
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;
}
} }
Thread thread = new Handler();
thread.setUncaughtExceptionHandler(new DefaultUncaughtExceptionHandler(LOGGER)); this.secretKey = packetIn.getSecretKey(privatekey);
thread.start(); 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 { private void arclight$preLogin() throws Exception {

View File

@ -29,14 +29,12 @@ import net.minecraft.entity.player.ChatVisibility;
import net.minecraft.entity.player.PlayerInventory; import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.entity.projectile.AbstractArrowEntity; import net.minecraft.entity.projectile.AbstractArrowEntity;
import net.minecraft.inventory.EquipmentSlotType;
import net.minecraft.inventory.container.Container; import net.minecraft.inventory.container.Container;
import net.minecraft.inventory.container.MerchantContainer; import net.minecraft.inventory.container.MerchantContainer;
import net.minecraft.inventory.container.Slot; import net.minecraft.inventory.container.Slot;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.item.Items; import net.minecraft.item.Items;
import net.minecraft.item.WritableBookItem;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.ListNBT; import net.minecraft.nbt.ListNBT;
import net.minecraft.nbt.StringNBT; 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 org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.util.Collections; import java.util.Collections;
import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
@ -409,47 +408,57 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
CraftEventFactory.callTradeSelectEvent(this.player, i, (MerchantContainer) container); CraftEventFactory.callTradeSelectEvent(this.player, i, (MerchantContainer) container);
} }
/** @Inject(method = "processEditBook", cancellable = true, at = @At("HEAD"))
* @author IzzelAliz private void arclight$editBookSpam(CEditBookPacket packetIn, CallbackInfo ci) {
* @reason
*/
@Overwrite
public void processEditBook(CEditBookPacket packetplayinbedit) {
PacketThreadUtil.checkThreadAndEnqueue(packetplayinbedit, (ServerPlayNetHandler) (Object) this, this.player.getServerWorld());
if (lastBookTick == 0) lastBookTick = ArclightConstants.currentTick;
if (this.lastBookTick + 20 > ArclightConstants.currentTick) { if (this.lastBookTick + 20 > ArclightConstants.currentTick) {
this.disconnect("Book edited too quickly!"); this.disconnect("Book edited too quickly!");
return; return;
} }
this.lastBookTick = ArclightConstants.currentTick; 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()); * @author IzzelAliz
if (itemstack.getItem() == Items.WRITABLE_BOOK && itemstack2.getItem() == Items.WRITABLE_BOOK) { * @reason
if (packetplayinbedit.shouldUpdateAll()) { */
ItemStack itemstack3 = new ItemStack(Items.WRITTEN_BOOK); @Overwrite
CompoundNBT nbttagcompound = itemstack2.getTag(); private void func_244536_a(List<String> p_244536_1_, int p_244536_2_) {
if (nbttagcompound != null) { ItemStack itemstack = this.player.inventory.getStackInSlot(p_244536_2_);
itemstack3.setTag(nbttagcompound.copy()); if (itemstack.getItem() == Items.WRITABLE_BOOK) {
} ListNBT listnbt = new ListNBT();
itemstack3.setTagInfo("author", StringNBT.valueOf(this.player.getName().getString())); p_244536_1_.stream().map(StringNBT::valueOf).forEach(listnbt::add);
itemstack3.setTagInfo("title", StringNBT.valueOf(itemstack.getTag().getString("title"))); ItemStack old = itemstack.copy();
ListNBT nbttaglist = itemstack.getTag().getList("pages", 8); itemstack.setTagInfo("pages", listnbt);
for (int i = 0; i < nbttaglist.size(); ++i) { CraftEventFactory.handleEditBookEvent(player, p_244536_2_, old, itemstack);
String s = nbttaglist.getString(i); }
StringTextComponent chatcomponenttext = new StringTextComponent(s); }
s = ITextComponent.Serializer.toJson(chatcomponenttext);
nbttaglist.set(i, StringNBT.valueOf(s)); /**
} * @author IzzelAliz
itemstack3.setTagInfo("pages", nbttaglist); * @reason
this.player.setHeldItem(packetplayinbedit.getHand(), CraftEventFactory.handleEditBookEvent(this.player, enumitemslot, itemstack2, itemstack3)); */
} else { @Overwrite
ItemStack old = itemstack2.copy(); private void func_244534_a(String p_244534_1_, List<String> p_244534_2_, int p_244534_3_) {
itemstack2.setTagInfo("pages", itemstack.getTag().getList("pages", 8)); ItemStack itemstack = this.player.inventory.getStackInSlot(p_244534_3_);
CraftEventFactory.handleEditBookEvent(this.player, enumitemslot, old, itemstack2); 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("/")) { if (!async && s.startsWith("/")) {
this.handleSlashCommand(s); this.handleSlashCommand(s);
} else if (this.player.getChatVisibility() != ChatVisibility.SYSTEM) { } else if (this.player.getChatVisibility() != ChatVisibility.SYSTEM) {
Player player = this.getPlayer(); Player thisPlayer = this.getPlayer();
AsyncPlayerChatEvent event = new AsyncPlayerChatEvent(async, player, s, new LazyPlayerSet(this.minecraftServer)); AsyncPlayerChatEvent event = new AsyncPlayerChatEvent(async, thisPlayer, s, new LazyPlayerSet(this.minecraftServer));
this.server.getPluginManager().callEvent(event); this.server.getPluginManager().callEvent(event);
if (PlayerChatEvent.getHandlerList().getRegisteredListeners().length != 0) { 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()); queueEvent.setCancelled(event.isCancelled());
class SyncChat extends Waitable { class SyncChat extends Waitable {
@ -969,11 +978,11 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
Bukkit.getConsoleSender().sendMessage(CraftChatMessage.fromComponent(component)); Bukkit.getConsoleSender().sendMessage(CraftChatMessage.fromComponent(component));
if (((LazyPlayerSet) queueEvent.getRecipients()).isLazy()) { if (((LazyPlayerSet) queueEvent.getRecipients()).isLazy()) {
for (ServerPlayerEntity player : minecraftServer.getPlayerList().players) { for (ServerPlayerEntity player : minecraftServer.getPlayerList().players) {
((ServerPlayerEntityBridge) player).bridge$sendMessage(component); ((ServerPlayerEntityBridge) player).bridge$sendMessage(component, thisPlayer.getUniqueId());
} }
} else { } else {
for (Player player2 : queueEvent.getRecipients()) { for (Player player2 : queueEvent.getRecipients()) {
((ServerPlayerEntityBridge) ((CraftPlayer) player2).getHandle()).bridge$sendMessage(component); ((ServerPlayerEntityBridge) ((CraftPlayer) player2).getHandle()).bridge$sendMessage(component, thisPlayer.getUniqueId());
} }
} }
return null; return null;
@ -1010,11 +1019,11 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
Bukkit.getConsoleSender().sendMessage(CraftChatMessage.fromComponent(component)); Bukkit.getConsoleSender().sendMessage(CraftChatMessage.fromComponent(component));
if (((LazyPlayerSet) event.getRecipients()).isLazy()) { if (((LazyPlayerSet) event.getRecipients()).isLazy()) {
for (ServerPlayerEntity recipient : minecraftServer.getPlayerList().players) { for (ServerPlayerEntity recipient : minecraftServer.getPlayerList().players) {
((ServerPlayerEntityBridge) recipient).bridge$sendMessage(component); ((ServerPlayerEntityBridge) recipient).bridge$sendMessage(component, thisPlayer.getUniqueId());
} }
} else { } else {
for (Player recipient2 : event.getRecipients()) { for (Player recipient2 : event.getRecipients()) {
((ServerPlayerEntityBridge) ((CraftPlayer) recipient2).getHandle()).bridge$sendMessage(component); ((ServerPlayerEntityBridge) ((CraftPlayer) recipient2).getHandle()).bridge$sendMessage(component, thisPlayer.getUniqueId());
} }
} }
return null; 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")) @Inject(method = "func_244542_a", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/ServerPlayerEntity;markPlayerActive()V"))
private void arclight$noSignEdit(CUpdateSignPacket packetIn, CallbackInfo ci) { private void arclight$noSignEdit(CUpdateSignPacket p_244542_1_, List<String> p_244542_2_, CallbackInfo ci) {
if (((ServerPlayerEntityBridge) player).bridge$isMovementBlocked()) { if (((ServerPlayerEntityBridge) player).bridge$isMovementBlocked()) {
ci.cancel(); ci.cancel();
} }
@ -1606,11 +1615,11 @@ public abstract class ServerPlayNetHandlerMixin implements ServerPlayNetHandlerB
private ITextComponent[] arclight$lines; private ITextComponent[] arclight$lines;
@Inject(method = "processUpdateSign", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/network/play/client/CUpdateSignPacket;getLines()[Ljava/lang/String;")) @Inject(method = "func_244542_a", cancellable = true, at = @At(value = "INVOKE", target = "Lnet/minecraft/tileentity/SignTileEntity;getIsEditable()Z"))
public void arclight$onSignChangePre(CUpdateSignPacket packetIn, CallbackInfo ci) { public void arclight$onSignChangePre(CUpdateSignPacket p_244542_1_, List<String> p_244542_2_, CallbackInfo ci) {
String[] lines = packetIn.getLines(); String[] lines = p_244542_2_.toArray(new String[0]);
Player player = ((CraftServer) Bukkit.getServer()).getPlayer(this.player); 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]; String[] bukkitLines = new String[lines.length];
for (int i = 0; i < lines.length; i++) { for (int i = 0; i < lines.length; i++) {
bukkitLines[i] = TextFormatting.getTextWithoutFormattingCodes( 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) { public void arclight$onSignChangePost(SignTileEntity signTileEntity, int line, ITextComponent signText) {
if (arclight$lines != null) { if (arclight$lines != null) {
signTileEntity.setText(line, arclight$lines[line]); signTileEntity.setText(line, arclight$lines[line]);

View File

@ -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")) @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) { 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"); PlayerQuitEvent playerQuitEvent = new PlayerQuitEvent(cserver.getPlayer(playerIn), "\u00A7e" + playerIn.getScoreboardName() + " left the game");
cserver.getPluginManager().callEvent(playerQuitEvent); cserver.getPluginManager().callEvent(playerQuitEvent);
((ServerPlayerEntityBridge) playerIn).bridge$getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage()); ((ServerPlayerEntityBridge) playerIn).bridge$getBukkitEntity().disconnect(playerQuitEvent.getQuitMessage());

View File

@ -80,7 +80,7 @@ public abstract class TeleporterMixin implements TeleporterBridge {
} }
@SuppressWarnings({"unchecked", "rawtypes"}) @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<Optional<TeleportationRepositioner.Result>> cir) { private void arclight$portalCreate(BlockPos pos, Direction.Axis axis, CallbackInfoReturnable<Optional<TeleportationRepositioner.Result>> cir) {
CraftWorld craftWorld = ((WorldBridge) this.world).bridge$getWorld(); CraftWorld craftWorld = ((WorldBridge) this.world).bridge$getWorld();
List<org.bukkit.block.BlockState> blockStates; List<org.bukkit.block.BlockState> 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); 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); 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(); this.arclight$populator.updateList();
} }
} }

View File

@ -17,6 +17,8 @@ import net.minecraft.world.chunk.ChunkSection;
import net.minecraft.world.server.ServerWorld; import net.minecraft.world.server.ServerWorld;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v.CraftChunk; 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.bukkit.event.world.ChunkLoadEvent;
import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@ -48,6 +50,9 @@ public abstract class ChunkMixin implements ChunkBridge {
private transient boolean arclight$doPlace; private transient boolean arclight$doPlace;
public ServerWorld $$world; public ServerWorld $$world;
private static final CraftPersistentDataTypeRegistry DATA_TYPE_REGISTRY = new CraftPersistentDataTypeRegistry();
public final CraftPersistentDataContainer persistentDataContainer = new CraftPersistentDataContainer(DATA_TYPE_REGISTRY);
@Inject(method = "<init>(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")) @Inject(method = "<init>(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<Block> tickBlocksIn, ITickList<Fluid> tickFluidsIn, long inhabitedTimeIn, ChunkSection[] sectionsIn, Consumer<Chunk> postLoadConsumerIn, CallbackInfo ci) { private void arclight$init(World worldIn, ChunkPos chunkPosIn, BiomeContainer biomeContainerIn, UpgradeData upgradeDataIn, ITickList<Block> tickBlocksIn, ITickList<Fluid> tickFluidsIn, long inhabitedTimeIn, ChunkSection[] sectionsIn, Consumer<Chunk> postLoadConsumerIn, CallbackInfo ci) {
this.$$world = ((ServerWorld) worldIn); this.$$world = ((ServerWorld) worldIn);
@ -63,6 +68,11 @@ public abstract class ChunkMixin implements ChunkBridge {
return bukkitChunk; return bukkitChunk;
} }
@Override
public CraftPersistentDataContainer bridge$getPersistentContainer() {
return this.persistentDataContainer;
}
@Override @Override
public void bridge$setBukkitChunk(org.bukkit.Chunk chunk) { public void bridge$setBukkitChunk(org.bukkit.Chunk chunk) {
this.bukkitChunk = chunk; this.bukkitChunk = chunk;

View File

@ -13,6 +13,7 @@ public abstract class ArclightEventDispatcherRegistry {
MinecraftForge.EVENT_BUS.register(new EntityTeleportEventDispatcher()); MinecraftForge.EVENT_BUS.register(new EntityTeleportEventDispatcher());
MinecraftForge.EVENT_BUS.register(new ItemEntityEventDispatcher()); MinecraftForge.EVENT_BUS.register(new ItemEntityEventDispatcher());
MinecraftForge.EVENT_BUS.register(new WorldEventDispatcher()); MinecraftForge.EVENT_BUS.register(new WorldEventDispatcher());
MinecraftForge.EVENT_BUS.register(new ChunkEventHandler());
ArclightMod.LOGGER.info("registry.forge-event"); ArclightMod.LOGGER.info("registry.forge-event");
} }

View File

@ -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());
}
}
}
}

View File

@ -21,14 +21,14 @@ apply plugin: 'io.izzel.arclight'
apply plugin: 'maven-publish' apply plugin: 'maven-publish'
ext { ext {
minecraftVersion = '1.16.3' minecraftVersion = '1.16.4'
forgeVersion = '34.1.25' forgeVersion = '35.1.0'
} }
arclight { arclight {
mcVersion = minecraftVersion mcVersion = minecraftVersion
forgeVersion = project.ext.forgeVersion forgeVersion = project.ext.forgeVersion
bukkitVersion = 'v1_16_R2' bukkitVersion = 'v1_16_R3'
wipeVersion = true wipeVersion = true
reobfVersion = true reobfVersion = true
accessTransformer = project(':arclight-common').file('bukkit.at') accessTransformer = project(':arclight-common').file('bukkit.at')