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)
This commit is contained in:
IzzelAliz 2020-10-21 14:29:47 +08:00
parent 77ccfa00e5
commit 99d3bce676
12 changed files with 83 additions and 19 deletions

View File

@ -1,8 +1,11 @@
package io.izzel.arclight.common.bridge.bukkit; package io.izzel.arclight.common.bridge.bukkit;
import net.minecraft.server.management.PlayerList; import net.minecraft.server.management.PlayerList;
import net.minecraft.world.server.ServerWorld;
public interface CraftServerBridge { public interface CraftServerBridge {
void bridge$setPlayerList(PlayerList playerList); void bridge$setPlayerList(PlayerList playerList);
void bridge$removeWorld(ServerWorld world);
} }

View File

@ -1,10 +1,14 @@
package io.izzel.arclight.common.bridge.inventory; 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.ItemStack;
import net.minecraft.item.crafting.IRecipe; import net.minecraft.item.crafting.IRecipe;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.craftbukkit.v.entity.CraftHumanEntity; import org.bukkit.craftbukkit.v.entity.CraftHumanEntity;
import org.bukkit.craftbukkit.v.inventory.CraftInventory;
import org.bukkit.entity.HumanEntity; import org.bukkit.entity.HumanEntity;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.InventoryHolder;
import java.util.List; import java.util.List;
@ -32,4 +36,14 @@ public interface IInventoryBridge {
IRecipe<?> getCurrentRecipe(); IRecipe<?> getCurrentRecipe();
void setCurrentRecipe(IRecipe<?> recipe); 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);
}
}
} }

View File

@ -1,13 +1,19 @@
package io.izzel.arclight.common.mixin.bukkit; package io.izzel.arclight.common.mixin.bukkit;
import io.izzel.arclight.common.bridge.bukkit.CraftServerBridge; import io.izzel.arclight.common.bridge.bukkit.CraftServerBridge;
import io.izzel.arclight.common.bridge.world.WorldBridge;
import jline.console.ConsoleReader; import jline.console.ConsoleReader;
import net.minecraft.command.Commands; import net.minecraft.command.Commands;
import net.minecraft.server.dedicated.DedicatedPlayerList; import net.minecraft.server.dedicated.DedicatedPlayerList;
import net.minecraft.server.dedicated.DedicatedServer; import net.minecraft.server.dedicated.DedicatedServer;
import net.minecraft.server.management.PlayerList; 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.command.Command;
import org.bukkit.craftbukkit.v.CraftServer; 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.BukkitCommandWrapper;
import org.bukkit.craftbukkit.v.command.CraftCommandMap; import org.bukkit.craftbukkit.v.command.CraftCommandMap;
import org.bukkit.craftbukkit.v.help.SimpleHelpMap; 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.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.io.IOException; import java.io.IOException;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.logging.Logger; 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 protected DedicatedServer console;
@Shadow(remap = false) @Final @Mutable private String serverName; @Shadow(remap = false) @Final @Mutable private String serverName;
@Shadow(remap = false) @Final @Mutable protected DedicatedPlayerList playerList; @Shadow(remap = false) @Final @Mutable protected DedicatedPlayerList playerList;
@Shadow(remap = false) @Final private Map<String, World> worlds;
@Accessor(value = "logger", remap = false) @Mutable public abstract void setLogger(Logger logger); @Accessor(value = "logger", remap = false) @Mutable public abstract void setLogger(Logger logger);
// @formatter:on // @formatter:on
@ -120,4 +129,17 @@ public abstract class CraftServerMixin implements CraftServerBridge {
public void bridge$setPlayerList(PlayerList playerList) { public void bridge$setPlayerList(PlayerList playerList) {
this.playerList = (DedicatedPlayerList) 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<Boolean> 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));
}
} }

View File

@ -4,6 +4,7 @@ import io.izzel.arclight.common.bridge.world.WorldBridge;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.CarvedPumpkinBlock; import net.minecraft.block.CarvedPumpkinBlock;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.common.util.Constants; import net.minecraftforge.common.util.Constants;
@ -50,13 +51,15 @@ public class CarvedPumpkinBlockMixin {
arclight$success = false; arclight$success = false;
} }
@Inject(method = "trySpawnGolem", at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/world/World;addEntity(Lnet/minecraft/entity/Entity;)Z")) @Redirect(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) { public boolean arclight$spawnSnow(World world, Entity entityIn) {
((WorldBridge) world).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.BUILD_SNOWMAN); ((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")) @Redirect(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) { public boolean arclight$spawnIron(World world, Entity entityIn) {
((WorldBridge) world).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.BUILD_IRONGOLEM); ((WorldBridge) world).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.BUILD_IRONGOLEM);
return arclight$success = world.addEntity(entityIn);
} }
} }

View File

@ -55,7 +55,7 @@ public class DropperBlockMixin {
if (iinventory instanceof DoubleSidedInventory) { if (iinventory instanceof DoubleSidedInventory) {
destinationInventory = new CraftInventoryDoubleChest((DoubleSidedInventory) iinventory); destinationInventory = new CraftInventoryDoubleChest((DoubleSidedInventory) iinventory);
} else { } else {
destinationInventory = ((IInventoryBridge) iinventory).getOwner().getInventory(); destinationInventory = ((IInventoryBridge) iinventory).getOwnerInventory();
} }
InventoryMoveItemEvent event = new InventoryMoveItemEvent(((IInventoryBridge) dispensertileentity).getOwner().getInventory(), craftItemStack, destinationInventory, true); InventoryMoveItemEvent event = new InventoryMoveItemEvent(((IInventoryBridge) dispensertileentity).getOwner().getInventory(), craftItemStack, destinationInventory, true);
Bukkit.getPluginManager().callEvent(event); Bukkit.getPluginManager().callEvent(event);

View File

@ -4,6 +4,7 @@ import io.izzel.arclight.common.bridge.world.WorldBridge;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.WitherSkeletonSkullBlock; import net.minecraft.block.WitherSkeletonSkullBlock;
import net.minecraft.entity.Entity;
import net.minecraft.tileentity.SkullTileEntity; import net.minecraft.tileentity.SkullTileEntity;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
@ -51,8 +52,9 @@ public class WitherSkeletonSkullBlockMixin {
arclight$success = false; arclight$success = false;
} }
@Inject(method = "checkWitherSpawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;addEntity(Lnet/minecraft/entity/Entity;)Z")) @Redirect(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) { private static boolean arclight$spawnWither(World world, Entity entityIn) {
((WorldBridge) worldIn).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.BUILD_WITHER); ((WorldBridge) world).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.BUILD_WITHER);
return arclight$success = world.addEntity(entityIn);
} }
} }

View File

@ -64,7 +64,7 @@ public abstract class HopperTileEntityMixin extends LockableTileEntityMixin {
if (destination instanceof DoubleSidedInventory) { if (destination instanceof DoubleSidedInventory) {
destinationInventory = new CraftInventoryDoubleChest(((DoubleSidedInventory) destination)); destinationInventory = new CraftInventoryDoubleChest(((DoubleSidedInventory) destination));
} else { } else {
destinationInventory = ((IInventoryBridge) destination).getOwner().getInventory(); destinationInventory = ((IInventoryBridge) destination).getOwnerInventory();
} }
InventoryMoveItemEvent event = new InventoryMoveItemEvent(this.getOwner().getInventory(), original.clone(), destinationInventory, true); 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) { if (source instanceof DoubleSidedInventory) {
sourceInventory = new CraftInventoryDoubleChest(((DoubleSidedInventory) source)); sourceInventory = new CraftInventoryDoubleChest(((DoubleSidedInventory) source));
} else { } 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); Bukkit.getPluginManager().callEvent(event);
if (arclight$moveItem = event.isCancelled()) { if (arclight$moveItem = event.isCancelled()) {
if (destination instanceof HopperTileEntity) { if (destination instanceof HopperTileEntity) {
@ -112,7 +112,7 @@ public abstract class HopperTileEntityMixin extends LockableTileEntityMixin {
@Inject(method = "captureItem", cancellable = true, at = @At("HEAD")) @Inject(method = "captureItem", cancellable = true, at = @At("HEAD"))
private static void arclight$pickupItem(IInventory inventory, ItemEntity itemEntity, CallbackInfoReturnable<Boolean> cir) { private static void arclight$pickupItem(IInventory inventory, ItemEntity itemEntity, CallbackInfoReturnable<Boolean> 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); Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled()) { if (event.isCancelled()) {
cir.setReturnValue(false); cir.setReturnValue(false);

View File

@ -388,6 +388,10 @@ public abstract class ServerWorldMixin extends WorldMixin implements ServerWorld
if (registryName == null || !registryName.getNamespace().equals("minecraft")) { if (registryName == null || !registryName.getNamespace().equals("minecraft")) {
return found; 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}" + ". " 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}); + "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});

View File

@ -17,8 +17,10 @@ import io.izzel.arclight.i18n.ArclightConfig;
import io.izzel.arclight.i18n.conf.EntityPropertySpec; import io.izzel.arclight.i18n.conf.EntityPropertySpec;
import io.izzel.arclight.i18n.conf.MaterialPropertySpec; import io.izzel.arclight.i18n.conf.MaterialPropertySpec;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
import net.minecraft.entity.merchant.villager.VillagerProfession; import net.minecraft.entity.merchant.villager.VillagerProfession;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.item.Items;
import net.minecraft.potion.Effect; import net.minecraft.potion.Effect;
import net.minecraft.util.RegistryKey; import net.minecraft.util.RegistryKey;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
@ -224,7 +226,7 @@ public class BukkitRegistry {
BLOCK_MATERIAL.put(block, material); BLOCK_MATERIAL.put(block, material);
MATERIAL_BLOCK.put(material, block); MATERIAL_BLOCK.put(material, block);
Item value = ForgeRegistries.ITEMS.getValue(location); Item value = ForgeRegistries.ITEMS.getValue(location);
if (value != null) { if (value != null && value != Items.AIR) {
((MaterialBridge) (Object) material).bridge$setItem(); ((MaterialBridge) (Object) material).bridge$setItem();
ITEM_MATERIAL.put(value, material); ITEM_MATERIAL.put(value, material);
MATERIAL_ITEM.put(material, value); MATERIAL_ITEM.put(material, value);
@ -246,7 +248,7 @@ public class BukkitRegistry {
ITEM_MATERIAL.put(item, material); ITEM_MATERIAL.put(item, material);
MATERIAL_ITEM.put(material, item); MATERIAL_ITEM.put(material, item);
Block value = ForgeRegistries.BLOCKS.getValue(location); Block value = ForgeRegistries.BLOCKS.getValue(location);
if (value != null) { if (value != null && value != Blocks.AIR) {
((MaterialBridge) (Object) material).bridge$setBlock(); ((MaterialBridge) (Object) material).bridge$setBlock();
BLOCK_MATERIAL.put(value, material); BLOCK_MATERIAL.put(value, material);
MATERIAL_BLOCK.put(material, value); MATERIAL_BLOCK.put(material, value);

View File

@ -12,6 +12,7 @@ public abstract class ArclightEventDispatcherRegistry {
MinecraftForge.EVENT_BUS.register(new EntityEventDispatcher()); MinecraftForge.EVENT_BUS.register(new EntityEventDispatcher());
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());
ArclightMod.LOGGER.info("registry.forge-event"); ArclightMod.LOGGER.info("registry.forge-event");
} }

View File

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

View File

@ -128,11 +128,7 @@ public class ArclightCaptures {
private static transient Container arclight$capturedContainer; private static transient Container arclight$capturedContainer;
public static void captureWorkbenchContainer(Container container) { public static void captureWorkbenchContainer(Container container) {
if (arclight$capturedContainer == null) { arclight$capturedContainer = container;
arclight$capturedContainer = container;
} else {
recapture("workbench container");
}
} }
public static Container getWorkbenchContainer() { public static Container getWorkbenchContainer() {