From 99d3bce6764b8f5b5cdcd130eb68f286a996b5f7 Mon Sep 17 00:00:00 2001 From: IzzelAliz Date: Wed, 21 Oct 2020 14:29:47 +0800 Subject: [PATCH] Port fixes of #28 #65 Call forge event when bukkit load world and vise versa Allow recapture container for fast workbench Fix golem and wither spawn not consuming blocks Fix some inventory missing an owner (#65) Fix wrong mapping with air block and item (#28) --- .../bridge/bukkit/CraftServerBridge.java | 3 +++ .../bridge/inventory/IInventoryBridge.java | 14 ++++++++++++ .../common/mixin/bukkit/CraftServerMixin.java | 22 +++++++++++++++++++ .../core/block/CarvedPumpkinBlockMixin.java | 11 ++++++---- .../mixin/core/block/DropperBlockMixin.java | 2 +- .../block/WitherSkeletonSkullBlockMixin.java | 8 ++++--- .../tileentity/HopperTileEntityMixin.java | 8 +++---- .../core/world/server/ServerWorldMixin.java | 4 ++++ .../common/mod/server/BukkitRegistry.java | 6 +++-- .../ArclightEventDispatcherRegistry.java | 1 + .../server/event/WorldEventDispatcher.java | 17 ++++++++++++++ .../common/mod/util/ArclightCaptures.java | 6 +---- 12 files changed, 83 insertions(+), 19 deletions(-) create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mod/server/event/WorldEventDispatcher.java diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/bukkit/CraftServerBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/bukkit/CraftServerBridge.java index 974e199c..f2bbf4c7 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/bukkit/CraftServerBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/bukkit/CraftServerBridge.java @@ -1,8 +1,11 @@ package io.izzel.arclight.common.bridge.bukkit; import net.minecraft.server.management.PlayerList; +import net.minecraft.world.server.ServerWorld; public interface CraftServerBridge { void bridge$setPlayerList(PlayerList playerList); + + void bridge$removeWorld(ServerWorld world); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/inventory/IInventoryBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/inventory/IInventoryBridge.java index 4eb0bb6c..c9fc518c 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/inventory/IInventoryBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/inventory/IInventoryBridge.java @@ -1,10 +1,14 @@ package io.izzel.arclight.common.bridge.inventory; +import io.izzel.arclight.common.mod.ArclightMod; +import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.IRecipe; import org.bukkit.Location; import org.bukkit.craftbukkit.v.entity.CraftHumanEntity; +import org.bukkit.craftbukkit.v.inventory.CraftInventory; import org.bukkit.entity.HumanEntity; +import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryHolder; import java.util.List; @@ -32,4 +36,14 @@ public interface IInventoryBridge { IRecipe getCurrentRecipe(); void setCurrentRecipe(IRecipe recipe); + + default Inventory getOwnerInventory() { + InventoryHolder owner = this.getOwner(); + if (owner != null) { + return owner.getInventory(); + } else { + ArclightMod.LOGGER.warn("No owner for inventory {}/{}", this, this.getClass()); + return new CraftInventory((IInventory) this); + } + } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/CraftServerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/CraftServerMixin.java index 0b255b8b..f9901c8c 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/CraftServerMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/bukkit/CraftServerMixin.java @@ -1,13 +1,19 @@ package io.izzel.arclight.common.mixin.bukkit; import io.izzel.arclight.common.bridge.bukkit.CraftServerBridge; +import io.izzel.arclight.common.bridge.world.WorldBridge; import jline.console.ConsoleReader; import net.minecraft.command.Commands; import net.minecraft.server.dedicated.DedicatedPlayerList; import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.server.management.PlayerList; +import net.minecraft.world.server.ServerWorld; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.world.WorldEvent; +import org.bukkit.World; import org.bukkit.command.Command; import org.bukkit.craftbukkit.v.CraftServer; +import org.bukkit.craftbukkit.v.CraftWorld; import org.bukkit.craftbukkit.v.command.BukkitCommandWrapper; import org.bukkit.craftbukkit.v.command.CraftCommandMap; import org.bukkit.craftbukkit.v.help.SimpleHelpMap; @@ -25,8 +31,10 @@ import org.spongepowered.asm.mixin.gen.Accessor; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.io.IOException; +import java.util.Locale; import java.util.Map; import java.util.logging.Logger; @@ -42,6 +50,7 @@ public abstract class CraftServerMixin implements CraftServerBridge { @Shadow(remap = false) @Final protected DedicatedServer console; @Shadow(remap = false) @Final @Mutable private String serverName; @Shadow(remap = false) @Final @Mutable protected DedicatedPlayerList playerList; + @Shadow(remap = false) @Final private Map worlds; @Accessor(value = "logger", remap = false) @Mutable public abstract void setLogger(Logger logger); // @formatter:on @@ -120,4 +129,17 @@ public abstract class CraftServerMixin implements CraftServerBridge { public void bridge$setPlayerList(PlayerList playerList) { this.playerList = (DedicatedPlayerList) playerList; } + + @Inject(method = "unloadWorld(Lorg/bukkit/World;Z)Z", require = 1, remap = false, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/server/ServerChunkProvider;close()V")) + private void arclight$unloadForge(World world, boolean save, CallbackInfoReturnable cir) { + MinecraftForge.EVENT_BUS.post(new WorldEvent.Unload(((CraftWorld) world).getHandle())); + } + + @Override + public void bridge$removeWorld(ServerWorld world) { + if (world == null) { + return; + } + this.worlds.remove(((WorldBridge) world).bridge$getWorld().getName().toLowerCase(Locale.ROOT)); + } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/block/CarvedPumpkinBlockMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/block/CarvedPumpkinBlockMixin.java index f3f2f4e2..06a25cb5 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/block/CarvedPumpkinBlockMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/block/CarvedPumpkinBlockMixin.java @@ -4,6 +4,7 @@ import io.izzel.arclight.common.bridge.world.WorldBridge; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.CarvedPumpkinBlock; +import net.minecraft.entity.Entity; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraftforge.common.util.Constants; @@ -50,13 +51,15 @@ public class CarvedPumpkinBlockMixin { arclight$success = false; } - @Inject(method = "trySpawnGolem", at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/world/World;addEntity(Lnet/minecraft/entity/Entity;)Z")) - public void arclight$spawnSnow(World world, BlockPos pos, CallbackInfo ci) { + @Redirect(method = "trySpawnGolem", at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/world/World;addEntity(Lnet/minecraft/entity/Entity;)Z")) + public boolean arclight$spawnSnow(World world, Entity entityIn) { ((WorldBridge) world).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.BUILD_SNOWMAN); + return arclight$success = world.addEntity(entityIn); } - @Inject(method = "trySpawnGolem", at = @At(value = "INVOKE", ordinal = 1, target = "Lnet/minecraft/world/World;addEntity(Lnet/minecraft/entity/Entity;)Z")) - public void arclight$spawnIron(World world, BlockPos pos, CallbackInfo ci) { + @Redirect(method = "trySpawnGolem", at = @At(value = "INVOKE", ordinal = 1, target = "Lnet/minecraft/world/World;addEntity(Lnet/minecraft/entity/Entity;)Z")) + public boolean arclight$spawnIron(World world, Entity entityIn) { ((WorldBridge) world).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.BUILD_IRONGOLEM); + return arclight$success = world.addEntity(entityIn); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/block/DropperBlockMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/block/DropperBlockMixin.java index 1f52a04f..4aba844b 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/block/DropperBlockMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/block/DropperBlockMixin.java @@ -55,7 +55,7 @@ public class DropperBlockMixin { if (iinventory instanceof DoubleSidedInventory) { destinationInventory = new CraftInventoryDoubleChest((DoubleSidedInventory) iinventory); } else { - destinationInventory = ((IInventoryBridge) iinventory).getOwner().getInventory(); + destinationInventory = ((IInventoryBridge) iinventory).getOwnerInventory(); } InventoryMoveItemEvent event = new InventoryMoveItemEvent(((IInventoryBridge) dispensertileentity).getOwner().getInventory(), craftItemStack, destinationInventory, true); Bukkit.getPluginManager().callEvent(event); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/block/WitherSkeletonSkullBlockMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/block/WitherSkeletonSkullBlockMixin.java index e506394b..e825d13a 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/block/WitherSkeletonSkullBlockMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/block/WitherSkeletonSkullBlockMixin.java @@ -4,6 +4,7 @@ import io.izzel.arclight.common.bridge.world.WorldBridge; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.WitherSkeletonSkullBlock; +import net.minecraft.entity.Entity; import net.minecraft.tileentity.SkullTileEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -51,8 +52,9 @@ public class WitherSkeletonSkullBlockMixin { arclight$success = false; } - @Inject(method = "checkWitherSpawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;addEntity(Lnet/minecraft/entity/Entity;)Z")) - private static void arclight$spawnWither(World worldIn, BlockPos pos, SkullTileEntity p_196298_2_, CallbackInfo ci) { - ((WorldBridge) worldIn).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.BUILD_WITHER); + @Redirect(method = "checkWitherSpawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;addEntity(Lnet/minecraft/entity/Entity;)Z")) + private static boolean arclight$spawnWither(World world, Entity entityIn) { + ((WorldBridge) world).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.BUILD_WITHER); + return arclight$success = world.addEntity(entityIn); } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/tileentity/HopperTileEntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/tileentity/HopperTileEntityMixin.java index 2eee1616..e379fdd7 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/tileentity/HopperTileEntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/tileentity/HopperTileEntityMixin.java @@ -64,7 +64,7 @@ public abstract class HopperTileEntityMixin extends LockableTileEntityMixin { if (destination instanceof DoubleSidedInventory) { destinationInventory = new CraftInventoryDoubleChest(((DoubleSidedInventory) destination)); } else { - destinationInventory = ((IInventoryBridge) destination).getOwner().getInventory(); + destinationInventory = ((IInventoryBridge) destination).getOwnerInventory(); } InventoryMoveItemEvent event = new InventoryMoveItemEvent(this.getOwner().getInventory(), original.clone(), destinationInventory, true); @@ -94,10 +94,10 @@ public abstract class HopperTileEntityMixin extends LockableTileEntityMixin { if (source instanceof DoubleSidedInventory) { sourceInventory = new CraftInventoryDoubleChest(((DoubleSidedInventory) source)); } else { - sourceInventory = ((IInventoryBridge) source).getOwner().getInventory(); + sourceInventory = ((IInventoryBridge) source).getOwnerInventory(); } - InventoryMoveItemEvent event = new InventoryMoveItemEvent(sourceInventory, original.clone(), ((IInventoryBridge) destination).getOwner().getInventory(), false); + InventoryMoveItemEvent event = new InventoryMoveItemEvent(sourceInventory, original.clone(), ((IInventoryBridge) destination).getOwnerInventory(), false); Bukkit.getPluginManager().callEvent(event); if (arclight$moveItem = event.isCancelled()) { if (destination instanceof HopperTileEntity) { @@ -112,7 +112,7 @@ public abstract class HopperTileEntityMixin extends LockableTileEntityMixin { @Inject(method = "captureItem", cancellable = true, at = @At("HEAD")) private static void arclight$pickupItem(IInventory inventory, ItemEntity itemEntity, CallbackInfoReturnable cir) { - InventoryPickupItemEvent event = new InventoryPickupItemEvent(((IInventoryBridge) inventory).getOwner().getInventory(), (Item) ((EntityBridge) itemEntity).bridge$getBukkitEntity()); + InventoryPickupItemEvent event = new InventoryPickupItemEvent(((IInventoryBridge) inventory).getOwnerInventory(), (Item) ((EntityBridge) itemEntity).bridge$getBukkitEntity()); Bukkit.getPluginManager().callEvent(event); if (event.isCancelled()) { cir.setReturnValue(false); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/server/ServerWorldMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/server/ServerWorldMixin.java index e870965b..c58c4846 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/server/ServerWorldMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/server/ServerWorldMixin.java @@ -388,6 +388,10 @@ public abstract class ServerWorldMixin extends WorldMixin implements ServerWorld if (registryName == null || !registryName.getNamespace().equals("minecraft")) { return found; } + ResourceLocation blockType = type.getRegistryName(); + if (blockType == null || !blockType.getNamespace().equals("minecraft")) { + return found; + } this.getServer().getLogger().log(Level.SEVERE, "Block at {0}, {1}, {2} is {3} but has {4}" + ". " + "Bukkit will attempt to fix this, but there may be additional damage that we cannot recover.", new Object[]{pos.getX(), pos.getY(), pos.getZ(), type, found}); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/BukkitRegistry.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/BukkitRegistry.java index c08495d3..a93980f7 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/BukkitRegistry.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/BukkitRegistry.java @@ -17,8 +17,10 @@ import io.izzel.arclight.i18n.ArclightConfig; import io.izzel.arclight.i18n.conf.EntityPropertySpec; import io.izzel.arclight.i18n.conf.MaterialPropertySpec; import net.minecraft.block.Block; +import net.minecraft.block.Blocks; import net.minecraft.entity.merchant.villager.VillagerProfession; import net.minecraft.item.Item; +import net.minecraft.item.Items; import net.minecraft.potion.Effect; import net.minecraft.util.RegistryKey; import net.minecraft.util.ResourceLocation; @@ -224,7 +226,7 @@ public class BukkitRegistry { BLOCK_MATERIAL.put(block, material); MATERIAL_BLOCK.put(material, block); Item value = ForgeRegistries.ITEMS.getValue(location); - if (value != null) { + if (value != null && value != Items.AIR) { ((MaterialBridge) (Object) material).bridge$setItem(); ITEM_MATERIAL.put(value, material); MATERIAL_ITEM.put(material, value); @@ -246,7 +248,7 @@ public class BukkitRegistry { ITEM_MATERIAL.put(item, material); MATERIAL_ITEM.put(material, item); Block value = ForgeRegistries.BLOCKS.getValue(location); - if (value != null) { + if (value != null && value != Blocks.AIR) { ((MaterialBridge) (Object) material).bridge$setBlock(); BLOCK_MATERIAL.put(value, material); MATERIAL_BLOCK.put(material, value); 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 3ebf1217..98ab5165 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 @@ -12,6 +12,7 @@ public abstract class ArclightEventDispatcherRegistry { MinecraftForge.EVENT_BUS.register(new EntityEventDispatcher()); MinecraftForge.EVENT_BUS.register(new EntityTeleportEventDispatcher()); MinecraftForge.EVENT_BUS.register(new ItemEntityEventDispatcher()); + MinecraftForge.EVENT_BUS.register(new WorldEventDispatcher()); ArclightMod.LOGGER.info("registry.forge-event"); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/event/WorldEventDispatcher.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/event/WorldEventDispatcher.java new file mode 100644 index 00000000..fc6a512d --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/server/event/WorldEventDispatcher.java @@ -0,0 +1,17 @@ +package io.izzel.arclight.common.mod.server.event; + +import io.izzel.arclight.common.bridge.bukkit.CraftServerBridge; +import net.minecraft.world.server.ServerWorld; +import net.minecraftforge.event.world.WorldEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import org.bukkit.Bukkit; + +public class WorldEventDispatcher { + + @SubscribeEvent + public void onWorldUnload(WorldEvent.Unload event) { + if (event.getWorld() instanceof ServerWorld) { + ((CraftServerBridge) Bukkit.getServer()).bridge$removeWorld(((ServerWorld) event.getWorld())); + } + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/ArclightCaptures.java b/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/ArclightCaptures.java index e783470e..7918f0f5 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/ArclightCaptures.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mod/util/ArclightCaptures.java @@ -128,11 +128,7 @@ public class ArclightCaptures { private static transient Container arclight$capturedContainer; public static void captureWorkbenchContainer(Container container) { - if (arclight$capturedContainer == null) { - arclight$capturedContainer = container; - } else { - recapture("workbench container"); - } + arclight$capturedContainer = container; } public static Container getWorkbenchContainer() {