From 427548b2b15605677d1f8eb59f6c992f346fe4cf Mon Sep 17 00:00:00 2001 From: IzzelAliz Date: Sun, 14 Jun 2020 18:03:54 +0800 Subject: [PATCH] Random stuff --- .../common/bridge/world/WorldBridge.java | 3 + .../world/border/WorldBorderBridge.java | 10 ++ .../play/client/CChatMessagePacketMixin.java | 31 +++++ .../CPlayerTryUseItemOnBlockPacketMixin.java | 19 +++ .../client/CPlayerTryUseItemPacketMixin.java | 19 +++ .../play/server/SWorldBorderPacketMixin.java | 26 ++++ .../common/mixin/core/world/WorldMixin.java | 10 +- .../core/world/border/WorldBorderMixin.java | 22 +++ .../core/world/raid/RaidManagerMixin.java | 2 +- .../mixin/core/world/raid/RaidMixin.java | 9 +- .../core/world/server/ChunkHolderMixin.java | 59 ++++---- .../world/spawner/AbstractSpawnerMixin.java | 130 ++++++++++++++++++ .../world/spawner/PatrolSpawnerMixin.java | 2 +- .../world/spawner/PhantomSpawnerMixin.java | 2 +- .../spawner/WorldEntitySpawnerMixin_1_15.java | 32 +++++ .../resources/mixins.arclight.core.1_15.json | 1 + .../main/resources/mixins.arclight.core.json | 6 +- .../spawner/WorldEntitySpawnerMixin_1_14.java | 4 +- .../resources/mixins.arclight.core.1_14.json | 3 +- 19 files changed, 355 insertions(+), 35 deletions(-) create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/bridge/world/border/WorldBorderBridge.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/play/client/CChatMessagePacketMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/play/client/CPlayerTryUseItemOnBlockPacketMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/play/client/CPlayerTryUseItemPacketMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/play/server/SWorldBorderPacketMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/border/WorldBorderMixin.java create mode 100644 arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/world/spawner/WorldEntitySpawnerMixin_1_15.java rename arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/spawner/WorldEntitySpawnerMixin.java => arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/world/spawner/WorldEntitySpawnerMixin_1_14.java (93%) diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/world/WorldBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/world/WorldBridge.java index 6f3c061d..5b177df2 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/world/WorldBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/world/WorldBridge.java @@ -5,6 +5,7 @@ import net.minecraft.util.math.BlockPos; import org.bukkit.craftbukkit.v.CraftServer; import org.bukkit.craftbukkit.v.CraftWorld; import org.bukkit.generator.ChunkGenerator; +import org.spigotmc.SpigotWorldConfig; public interface WorldBridge extends IWorldWriterBridge { @@ -23,4 +24,6 @@ public interface WorldBridge extends IWorldWriterBridge { ChunkGenerator bridge$getGenerator(); TileEntity bridge$getTileEntity(BlockPos pos, boolean validate); + + SpigotWorldConfig bridge$spigotConfig(); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/world/border/WorldBorderBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/world/border/WorldBorderBridge.java new file mode 100644 index 00000000..dc92c9b6 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/world/border/WorldBorderBridge.java @@ -0,0 +1,10 @@ +package io.izzel.arclight.common.bridge.world.border; + +import net.minecraft.world.server.ServerWorld; + +public interface WorldBorderBridge { + + ServerWorld bridge$getWorld(); + + void bridge$setWorld(ServerWorld world); +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/play/client/CChatMessagePacketMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/play/client/CChatMessagePacketMixin.java new file mode 100644 index 00000000..2938e5a3 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/play/client/CChatMessagePacketMixin.java @@ -0,0 +1,31 @@ +package io.izzel.arclight.common.mixin.core.network.play.client; + +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import net.minecraft.network.play.IServerPlayNetHandler; +import net.minecraft.network.play.client.CChatMessagePacket; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +@Mixin(CChatMessagePacket.class) +public class CChatMessagePacketMixin { + + @Shadow private String message; + + private static final ExecutorService executors = Executors.newCachedThreadPool( + new ThreadFactoryBuilder().setDaemon(true).setNameFormat("Async Chat Thread - #%d").build() + ); + + @Inject(method = "processPacket", cancellable = true, at = @At("HEAD")) + private void arclight$asyncChat(IServerPlayNetHandler handler, CallbackInfo ci) { + if (!this.message.startsWith("/")) { + executors.submit(() -> handler.processChatMessage((CChatMessagePacket) (Object) this)); + ci.cancel(); + } + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/play/client/CPlayerTryUseItemOnBlockPacketMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/play/client/CPlayerTryUseItemOnBlockPacketMixin.java new file mode 100644 index 00000000..43f316a5 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/play/client/CPlayerTryUseItemOnBlockPacketMixin.java @@ -0,0 +1,19 @@ +package io.izzel.arclight.common.mixin.core.network.play.client; + +import net.minecraft.network.PacketBuffer; +import net.minecraft.network.play.client.CPlayerTryUseItemOnBlockPacket; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(CPlayerTryUseItemOnBlockPacket.class) +public class CPlayerTryUseItemOnBlockPacketMixin { + + public long timestamp; + + @Inject(method = "readPacketData", at = @At("HEAD")) + private void arclight$read(PacketBuffer buf, CallbackInfo ci) { + this.timestamp = System.currentTimeMillis(); + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/play/client/CPlayerTryUseItemPacketMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/play/client/CPlayerTryUseItemPacketMixin.java new file mode 100644 index 00000000..d4b7d9cd --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/play/client/CPlayerTryUseItemPacketMixin.java @@ -0,0 +1,19 @@ +package io.izzel.arclight.common.mixin.core.network.play.client; + +import net.minecraft.network.PacketBuffer; +import net.minecraft.network.play.client.CPlayerTryUseItemPacket; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(CPlayerTryUseItemPacket.class) +public class CPlayerTryUseItemPacketMixin { + + public long timestamp; + + @Inject(method = "readPacketData", at = @At("HEAD")) + private void arclight$read(PacketBuffer buf, CallbackInfo ci) { + this.timestamp = System.currentTimeMillis(); + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/play/server/SWorldBorderPacketMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/play/server/SWorldBorderPacketMixin.java new file mode 100644 index 00000000..57b50c6b --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/network/play/server/SWorldBorderPacketMixin.java @@ -0,0 +1,26 @@ +package io.izzel.arclight.common.mixin.core.network.play.server; + +import io.izzel.arclight.common.bridge.world.border.WorldBorderBridge; +import net.minecraft.network.play.server.SWorldBorderPacket; +import net.minecraft.world.border.WorldBorder; +import net.minecraft.world.dimension.NetherDimension; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(SWorldBorderPacket.class) +public class SWorldBorderPacketMixin { + + // @formatter:off + @Shadow private double centerX; + @Shadow private double centerZ; + // @formatter:on + + @Inject(method = "(Lnet/minecraft/world/border/WorldBorder;Lnet/minecraft/network/play/server/SWorldBorderPacket$Action;)V", at = @At("RETURN")) + private void arclight$nether(WorldBorder border, SWorldBorderPacket.Action actionIn, CallbackInfo ci) { + this.centerX = border.getCenterX() * ((((WorldBorderBridge) border).bridge$getWorld().dimension instanceof NetherDimension) ? 8 : 1); + this.centerZ = border.getCenterZ() * ((((WorldBorderBridge) border).bridge$getWorld().dimension instanceof NetherDimension) ? 8 : 1); + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/WorldMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/WorldMixin.java index 01fe3a00..b261f1da 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/WorldMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/WorldMixin.java @@ -1,6 +1,8 @@ package io.izzel.arclight.common.mixin.core.world; import io.izzel.arclight.common.bridge.world.WorldBridge; +import io.izzel.arclight.common.bridge.world.border.WorldBorderBridge; +import io.izzel.arclight.common.mod.util.ArclightCaptures; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.entity.Entity; @@ -34,7 +36,6 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; -import io.izzel.arclight.common.mod.util.ArclightCaptures; import javax.annotation.Nullable; import java.util.function.BiFunction; @@ -52,6 +53,7 @@ public abstract class WorldMixin implements WorldBridge { @Shadow public abstract long getSeed(); @Shadow @Final public WorldInfo worldInfo; @Shadow public abstract WorldBorder getWorldBorder(); + @Shadow@Final private WorldBorder worldBorder; @Accessor("mainThread") public abstract Thread arclight$getMainThread(); // @formatter:on @@ -66,6 +68,7 @@ public abstract class WorldMixin implements WorldBridge { @Inject(method = "(Lnet/minecraft/world/storage/WorldInfo;Lnet/minecraft/world/dimension/DimensionType;Ljava/util/function/BiFunction;Lnet/minecraft/profiler/IProfiler;Z)V", at = @At("RETURN")) private void arclight$init(WorldInfo info, DimensionType dimType, BiFunction provider, IProfiler profilerIn, boolean remote, CallbackInfo ci) { spigotConfig = new SpigotWorldConfig(worldInfo.getWorldName()); + ((WorldBorderBridge) this.worldBorder).bridge$setWorld((ServerWorld) (Object) this); } public void arclight$constructor(WorldInfo info, DimensionType dimType, BiFunction provider, IProfiler profilerIn, boolean remote) { @@ -79,6 +82,11 @@ public abstract class WorldMixin implements WorldBridge { bridge$getWorld(); } + @Override + public SpigotWorldConfig bridge$spigotConfig() { + return this.spigotConfig; + } + @Inject(method = "setBlockState(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/block/BlockState;I)Z", at = @At("HEAD"), cancellable = true) private void arclight$hooks(BlockPos pos, BlockState newState, int flags, CallbackInfoReturnable cir) { diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/border/WorldBorderMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/border/WorldBorderMixin.java new file mode 100644 index 00000000..cbb03c70 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/border/WorldBorderMixin.java @@ -0,0 +1,22 @@ +package io.izzel.arclight.common.mixin.core.world.border; + +import io.izzel.arclight.common.bridge.world.border.WorldBorderBridge; +import net.minecraft.world.border.WorldBorder; +import net.minecraft.world.server.ServerWorld; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(WorldBorder.class) +public class WorldBorderMixin implements WorldBorderBridge { + + public ServerWorld world; + + @Override + public ServerWorld bridge$getWorld() { + return this.world; + } + + @Override + public void bridge$setWorld(ServerWorld world) { + this.world = world; + } +} diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/raid/RaidManagerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/raid/RaidManagerMixin.java index 74c03d68..ac7c5f23 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/raid/RaidManagerMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/raid/RaidManagerMixin.java @@ -21,7 +21,7 @@ import java.util.Map; public class RaidManagerMixin { // @formatter:off - @Shadow @Final private Map byId; + @Shadow @Final public Map byId; // @formatter:on @Inject(method = "badOmenTick", cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/raid/Raid;increaseLevel(Lnet/minecraft/entity/player/PlayerEntity;)V")) diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/raid/RaidMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/raid/RaidMixin.java index e58313c1..28c81ea1 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/raid/RaidMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/raid/RaidMixin.java @@ -31,9 +31,10 @@ import java.util.Set; @Mixin(Raid.class) public class RaidMixin implements RaidBridge { + // @formatter:off @Shadow @Final private Map> raiders; - @Shadow @Final private ServerWorld world; + // @formatter:on @Inject(method = "tick", at = @At(value = "INVOKE", ordinal = 0, target = "Lnet/minecraft/world/raid/Raid;stop()V")) public void arclight$stopPeace(CallbackInfo ci) { @@ -93,9 +94,9 @@ public class RaidMixin implements RaidBridge { arclight$leader = entity; } - @Redirect(method = "spawnNextWave", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/raid/Raid;func_221317_a(ILnet/minecraft/entity/monster/AbstractRaiderEntity;Lnet/minecraft/util/math/BlockPos;Z)V")) + @Redirect(method = "spawnNextWave", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/raid/Raid;joinRaid(ILnet/minecraft/entity/monster/AbstractRaiderEntity;Lnet/minecraft/util/math/BlockPos;Z)V")) public void arclight$captureRaider(Raid raid, int wave, AbstractRaiderEntity entity, BlockPos pos, boolean flag) { - raid.func_221317_a(wave, entity, pos, flag); + raid.joinRaid(wave, entity, pos, flag); if (arclight$raiders == null) { arclight$raiders = new ArrayList<>(); } @@ -107,7 +108,7 @@ public class RaidMixin implements RaidBridge { CraftEventFactory.callRaidSpawnWaveEvent((Raid) (Object) this, arclight$leader, arclight$raiders); } - @Inject(method = "func_221317_a", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/server/ServerWorld;addEntity(Lnet/minecraft/entity/Entity;)Z")) + @Inject(method = "joinRaid(ILnet/minecraft/entity/monster/AbstractRaiderEntity;Lnet/minecraft/util/math/BlockPos;Z)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/server/ServerWorld;addEntity(Lnet/minecraft/entity/Entity;)Z")) public void arclight$addEntity(int wave, AbstractRaiderEntity p_221317_2_, BlockPos p_221317_3_, boolean p_221317_4_, CallbackInfo ci) { ((WorldBridge) this.world).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.RAID); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/server/ChunkHolderMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/server/ChunkHolderMixin.java index bc882284..de83603d 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/server/ChunkHolderMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/server/ChunkHolderMixin.java @@ -4,12 +4,15 @@ import com.mojang.datafixers.util.Either; import io.izzel.arclight.common.bridge.world.chunk.ChunkBridge; import io.izzel.arclight.common.bridge.world.server.ChunkHolderBridge; import io.izzel.arclight.common.bridge.world.server.ChunkManagerBridge; +import io.izzel.arclight.common.mod.ArclightMod; +import net.minecraft.util.math.ChunkPos; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.ChunkStatus; import net.minecraft.world.chunk.IChunk; import net.minecraft.world.server.ChunkHolder; import net.minecraft.world.server.ChunkManager; import org.objectweb.asm.Opcodes; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.gen.Accessor; @@ -24,13 +27,14 @@ import java.util.concurrent.CompletableFuture; public abstract class ChunkHolderMixin implements ChunkHolderBridge { // @formatter:off - @Shadow public int field_219316_k; + @Shadow public int prevChunkLevel; @Shadow public abstract CompletableFuture> func_219301_a(ChunkStatus p_219301_1_); - @Override @Accessor("field_219316_k") public abstract int bridge$getOldTicketLevel(); + @Shadow @Final private ChunkPos pos; + @Override @Accessor("prevChunkLevel") public abstract int bridge$getOldTicketLevel(); // @formatter:on public Chunk getFullChunk() { - if (!ChunkHolder.func_219286_c(this.field_219316_k).func_219065_a(ChunkHolder.LocationType.BORDER)) { + if (!ChunkHolder.getLocationTypeFromLevel(this.prevChunkLevel).isAtLeast(ChunkHolder.LocationType.BORDER)) { return null; // note: using oldTicketLevel for isLoaded checks } CompletableFuture> statusFuture = this.func_219301_a(ChunkStatus.FULL); @@ -43,39 +47,48 @@ public abstract class ChunkHolderMixin implements ChunkHolderBridge { return this.getFullChunk(); } - @Inject(method = "func_219291_a", at = @At(value = "JUMP", opcode = Opcodes.IFEQ, ordinal = 0), + @Inject(method = "processUpdates", at = @At(value = "JUMP", opcode = Opcodes.IFEQ, ordinal = 0), locals = LocalCapture.CAPTURE_FAILHARD) public void arclight$onChunkUnload(ChunkManager chunkManager, CallbackInfo ci, ChunkStatus chunkStatus, ChunkStatus chunkStatus1, boolean flag, boolean flag1, ChunkHolder.LocationType locationType, ChunkHolder.LocationType locationType1) { - if (locationType.func_219065_a(ChunkHolder.LocationType.BORDER) && !locationType1.func_219065_a(ChunkHolder.LocationType.BORDER)) { - this.func_219301_a(ChunkStatus.FULL).thenAcceptAsync((either) -> { - either.ifLeft((chunkAccess) -> { - Chunk chunk = (Chunk) chunkAccess; - // Minecraft will apply the chunks tick lists to the world once the chunk got loaded, and then store the tick - // lists again inside the chunk once the chunk becomes inaccessible and set the chunk's needsSaving flag. - // These actions may however happen deferred, so we manually set the needsSaving flag already here. - chunk.setModified(true); - ((ChunkBridge) chunk).bridge$unloadCallback(); - }); - }, ((ChunkManagerBridge) chunkManager).bridge$getCallbackExecutor()); + if (locationType.isAtLeast(ChunkHolder.LocationType.BORDER) && !locationType1.isAtLeast(ChunkHolder.LocationType.BORDER)) { + this.func_219301_a(ChunkStatus.FULL).thenAccept((either) -> { + Chunk chunk = (Chunk) either.left().orElse(null); + if (chunk != null) { + ((ChunkManagerBridge) chunkManager).bridge$getCallbackExecutor().execute(() -> { + chunk.setModified(true); + ((ChunkBridge) chunk).bridge$unloadCallback(); + }); + } + }).exceptionally((throwable) -> { + // ensure exceptions are printed, by default this is not the case + ArclightMod.LOGGER.fatal("Failed to schedule unload callback for chunk " + this.pos, throwable); + return null; + }); // Run callback right away if the future was already done ((ChunkManagerBridge) chunkManager).bridge$getCallbackExecutor().run(); } } - @Inject(method = "func_219291_a", at = @At("RETURN"), locals = LocalCapture.CAPTURE_FAILHARD) + @Inject(method = "processUpdates", at = @At("RETURN"), locals = LocalCapture.CAPTURE_FAILHARD) public void arclight$onChunkLoad(ChunkManager chunkManager, CallbackInfo ci, ChunkStatus chunkStatus, ChunkStatus chunkStatus1, boolean flag, boolean flag1, ChunkHolder.LocationType locationType, ChunkHolder.LocationType locationType1) { - if (!locationType.func_219065_a(ChunkHolder.LocationType.BORDER) && locationType1.func_219065_a(ChunkHolder.LocationType.BORDER)) { - this.func_219301_a(ChunkStatus.FULL).thenAcceptAsync((either) -> { - either.ifLeft((chunkAccess) -> { - Chunk chunk = (Chunk) chunkAccess; - ((ChunkBridge) chunk).bridge$loadCallback(); - }); - }, ((ChunkManagerBridge) chunkManager).bridge$getCallbackExecutor()); + if (!locationType.isAtLeast(ChunkHolder.LocationType.BORDER) && locationType1.isAtLeast(ChunkHolder.LocationType.BORDER)) { + this.func_219301_a(ChunkStatus.FULL).thenAccept((either) -> { + Chunk chunk = (Chunk) either.left().orElse(null); + if (chunk != null) { + ((ChunkManagerBridge) chunkManager).bridge$getCallbackExecutor().execute( + ((ChunkBridge) chunk)::bridge$loadCallback + ); + } + }).exceptionally((throwable) -> { + // ensure exceptions are printed, by default this is not the case + ArclightMod.LOGGER.fatal("Failed to schedule load callback for chunk " + this.pos, throwable); + return null; + }); ((ChunkManagerBridge) chunkManager).bridge$getCallbackExecutor().run(); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/spawner/AbstractSpawnerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/spawner/AbstractSpawnerMixin.java index 8f1ba311..16ba09a4 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/spawner/AbstractSpawnerMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/spawner/AbstractSpawnerMixin.java @@ -1,20 +1,34 @@ package io.izzel.arclight.common.mixin.core.world.spawner; +import io.izzel.arclight.common.bridge.entity.MobEntityBridge; import io.izzel.arclight.common.bridge.world.WorldBridge; import net.minecraft.entity.Entity; +import net.minecraft.entity.EntitySpawnPlacementRegistry; import net.minecraft.entity.EntityType; +import net.minecraft.entity.ILivingEntityData; +import net.minecraft.entity.MobEntity; +import net.minecraft.entity.SpawnReason; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.ListNBT; +import net.minecraft.particles.ParticleTypes; import net.minecraft.util.WeightedSpawnerEntity; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraft.world.spawner.AbstractSpawner; +import net.minecraftforge.event.ForgeEventFactory; +import org.bukkit.craftbukkit.v.event.CraftEventFactory; import org.bukkit.event.entity.CreatureSpawnEvent; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.util.List; +import java.util.Optional; @Mixin(AbstractSpawner.class) public abstract class AbstractSpawnerMixin { @@ -22,6 +36,17 @@ public abstract class AbstractSpawnerMixin { // @formatter:off @Shadow public abstract World getWorld(); @Shadow @Final public List potentialSpawns; + @Shadow protected abstract boolean isActivated(); + @Shadow private double prevMobRotation; + @Shadow private double mobRotation; + @Shadow public abstract BlockPos getSpawnerPosition(); + @Shadow public int spawnDelay; + @Shadow protected abstract void resetTimer(); + @Shadow public int spawnCount; + @Shadow public WeightedSpawnerEntity spawnData; + @Shadow public int spawnRange; + @Shadow public int maxNearbyEntities; + @Shadow protected abstract void func_221409_a(Entity entityIn); // @formatter:on @Inject(method = "func_221409_a", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;addEntity(Lnet/minecraft/entity/Entity;)Z")) @@ -33,4 +58,109 @@ public abstract class AbstractSpawnerMixin { public void arclight$clearMobs(EntityType type, CallbackInfo ci) { this.potentialSpawns.clear(); } + + /** + * @author IzzelAliz + * @reason + */ + @Overwrite + public void tick() { + if (!this.isActivated()) { + this.prevMobRotation = this.mobRotation; + } else { + World world = this.getWorld(); + BlockPos blockpos = this.getSpawnerPosition(); + if (world.isRemote) { + double d3 = (double) blockpos.getX() + (double) world.rand.nextFloat(); + double d4 = (double) blockpos.getY() + (double) world.rand.nextFloat(); + double d5 = (double) blockpos.getZ() + (double) world.rand.nextFloat(); + world.addParticle(ParticleTypes.SMOKE, d3, d4, d5, 0.0D, 0.0D, 0.0D); + world.addParticle(ParticleTypes.FLAME, d3, d4, d5, 0.0D, 0.0D, 0.0D); + if (this.spawnDelay > 0) { + --this.spawnDelay; + } + + this.prevMobRotation = this.mobRotation; + this.mobRotation = (this.mobRotation + (double) (1000.0F / ((float) this.spawnDelay + 200.0F))) % 360.0D; + } else { + if (this.spawnDelay == -1) { + this.resetTimer(); + } + + if (this.spawnDelay > 0) { + --this.spawnDelay; + return; + } + + boolean flag = false; + + for (int i = 0; i < this.spawnCount; ++i) { + CompoundNBT compoundnbt = this.spawnData.getNbt(); + Optional> optional = EntityType.readEntityType(compoundnbt); + if (!optional.isPresent()) { + this.resetTimer(); + return; + } + + ListNBT listnbt = compoundnbt.getList("Pos", 6); + int j = listnbt.size(); + double d0 = j >= 1 ? listnbt.getDouble(0) : (double) blockpos.getX() + (world.rand.nextDouble() - world.rand.nextDouble()) * (double) this.spawnRange + 0.5D; + double d1 = j >= 2 ? listnbt.getDouble(1) : (double) (blockpos.getY() + world.rand.nextInt(3) - 1); + double d2 = j >= 3 ? listnbt.getDouble(2) : (double) blockpos.getZ() + (world.rand.nextDouble() - world.rand.nextDouble()) * (double) this.spawnRange + 0.5D; + if (world.hasNoCollisions(optional.get().getBoundingBoxWithSizeApplied(d0, d1, d2)) && EntitySpawnPlacementRegistry.func_223515_a(optional.get(), world.getWorld(), SpawnReason.SPAWNER, new BlockPos(d0, d1, d2), world.getRandom())) { + Entity entity = EntityType.loadEntityAndExecute(compoundnbt, world, (p_221408_6_) -> { + p_221408_6_.setLocationAndAngles(d0, d1, d2, p_221408_6_.rotationYaw, p_221408_6_.rotationPitch); + return p_221408_6_; + }); + if (entity == null) { + this.resetTimer(); + return; + } + + int k = world.getEntitiesWithinAABB(entity.getClass(), (new AxisAlignedBB((double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ(), (double) (blockpos.getX() + 1), (double) (blockpos.getY() + 1), (double) (blockpos.getZ() + 1))).grow((double) this.spawnRange)).size(); + if (k >= this.maxNearbyEntities) { + this.resetTimer(); + return; + } + + entity.setLocationAndAngles(entity.getPosX(), entity.getPosY(), entity.getPosZ(), world.rand.nextFloat() * 360.0F, 0.0F); + if (entity instanceof MobEntity) { + MobEntity mobentity = (MobEntity) entity; + if (!ForgeEventFactory.canEntitySpawnSpawner(mobentity, world, (float) entity.getPosX(), (float) entity.getPosY(), (float) entity.getPosZ(), (AbstractSpawner) (Object) this)) { + continue; + } + + if (this.spawnData.getNbt().size() == 1 && this.spawnData.getNbt().contains("id", 8)) { + ((MobEntity) entity).onInitialSpawn(world, world.getDifficultyForLocation(new BlockPos(entity)), SpawnReason.SPAWNER, (ILivingEntityData) null, (CompoundNBT) null); + } + + if (((WorldBridge) mobentity.world).bridge$spigotConfig().nerfSpawnerMobs) { + ((MobEntityBridge) mobentity).bridge$setAware(false); + } + } + if (CraftEventFactory.callSpawnerSpawnEvent(entity, blockpos).isCancelled()) { + Entity vehicle = entity.getRidingEntity(); + if (vehicle != null) { + vehicle.removed = true; + } + for (final Entity passenger : entity.getRecursivePassengers()) { + passenger.removed = true; + } + } + this.func_221409_a(entity); + world.playEvent(2004, blockpos, 0); + if (entity instanceof MobEntity) { + ((MobEntity) entity).spawnExplosionParticle(); + } + + flag = true; + } + } + + if (flag) { + this.resetTimer(); + } + } + } + } } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/spawner/PatrolSpawnerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/spawner/PatrolSpawnerMixin.java index 5fd22415..fd34c2eb 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/spawner/PatrolSpawnerMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/spawner/PatrolSpawnerMixin.java @@ -15,7 +15,7 @@ import java.util.Random; @Mixin(PatrolSpawner.class) public class PatrolSpawnerMixin { - @Inject(method = "func_222695_a", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;addEntity(Lnet/minecraft/entity/Entity;)Z")) + @Inject(method = "spawnPatroller", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;addEntity(Lnet/minecraft/entity/Entity;)Z")) public void arclight$spawnReanson(World worldIn, BlockPos p_222695_2_, Random random, boolean p_222695_4_, CallbackInfoReturnable cir) { ((WorldBridge) worldIn).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.PATROL); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/spawner/PhantomSpawnerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/spawner/PhantomSpawnerMixin.java index 89b86350..be67d81b 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/spawner/PhantomSpawnerMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/spawner/PhantomSpawnerMixin.java @@ -12,7 +12,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(PhantomSpawner.class) public class PhantomSpawnerMixin { - @Inject(method = "func_203232_a", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/server/ServerWorld;addEntity(Lnet/minecraft/entity/Entity;)Z")) + @Inject(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/server/ServerWorld;addEntity(Lnet/minecraft/entity/Entity;)Z")) public void arclight$spawnReason(ServerWorld worldIn, boolean spawnHostileMobs, boolean spawnPeacefulMobs, CallbackInfoReturnable cir) { ((WorldBridge) worldIn).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.NATURAL); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/world/spawner/WorldEntitySpawnerMixin_1_15.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/world/spawner/WorldEntitySpawnerMixin_1_15.java new file mode 100644 index 00000000..75f42856 --- /dev/null +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/v1_15/world/spawner/WorldEntitySpawnerMixin_1_15.java @@ -0,0 +1,32 @@ +package io.izzel.arclight.common.mixin.v1_15.world.spawner; + +import io.izzel.arclight.common.bridge.world.IWorldWriterBridge; +import io.izzel.arclight.common.bridge.world.WorldBridge; +import net.minecraft.entity.EntityClassification; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IWorld; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.server.ServerWorld; +import net.minecraft.world.spawner.WorldEntitySpawner; +import org.bukkit.event.entity.CreatureSpawnEvent; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.util.Random; + +@Mixin(WorldEntitySpawner.class) +public class WorldEntitySpawnerMixin_1_15 { + + @Inject(method = "spawnEntitiesInChunk", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/server/ServerWorld;addEntity(Lnet/minecraft/entity/Entity;)Z")) + private static void arclight$naturalSpawn(EntityClassification p_222263_0_, ServerWorld worldIn, Chunk p_222263_2_, BlockPos p_222263_3_, CallbackInfo ci) { + ((WorldBridge) worldIn).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.NATURAL); + } + + @Inject(method = "performWorldGenSpawning", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/IWorld;addEntity(Lnet/minecraft/entity/Entity;)Z")) + private static void arclight$worldGenSpawn(IWorld worldIn, Biome biomeIn, int centerX, int centerZ, Random diameterX, CallbackInfo ci) { + ((IWorldWriterBridge) worldIn).bridge$pushAddEntityReason(CreatureSpawnEvent.SpawnReason.CHUNK_GEN); + } +} diff --git a/arclight-common/src/main/resources/mixins.arclight.core.1_15.json b/arclight-common/src/main/resources/mixins.arclight.core.1_15.json index b3036947..769f3fe7 100644 --- a/arclight-common/src/main/resources/mixins.arclight.core.1_15.json +++ b/arclight-common/src/main/resources/mixins.arclight.core.1_15.json @@ -71,6 +71,7 @@ "world.chunk.ChunkMixin_1_15", "world.dimension.DimensionTypeMixin_1_15", "world.server.TicketManagerMixin_1_15", + "world.spawner.WorldEntitySpawnerMixin_1_15", "world.storage.loot.LootTableManagerMixin", "world.storage.loot.LootTableMixin" ] diff --git a/arclight-common/src/main/resources/mixins.arclight.core.json b/arclight-common/src/main/resources/mixins.arclight.core.json index d77831f1..3ecd0d25 100644 --- a/arclight-common/src/main/resources/mixins.arclight.core.json +++ b/arclight-common/src/main/resources/mixins.arclight.core.json @@ -288,8 +288,12 @@ "network.datasync.EntityDataManagerMixin", "network.login.ServerLoginNetHandler1Mixin", "network.play.ServerPlayNetHandlerMixin", + "network.play.client.CChatMessagePacketMixin", "network.play.client.CCloseWindowPacketMixin", + "network.play.client.CPlayerTryUseItemOnBlockPacketMixin", + "network.play.client.CPlayerTryUseItemPacketMixin", "network.play.server.SChatPacketMixin", + "network.play.server.SWorldBorderPacketMixin", "network.rcon.RConConsoleSourceMixin", "potion.EffectMixin", "server.CustomServerBossInfoMixin", @@ -334,6 +338,7 @@ "world.TeleporterMixin", "world.TrackedEntityMixin", "world.WorldMixin", + "world.border.WorldBorderMixin", "world.chunk.ChunkMixin", "world.chunk.storage.ChunkLoaderMixin", "world.chunk.storage.RegionFileCacheMixin", @@ -352,7 +357,6 @@ "world.spawner.PatrolSpawnerMixin", "world.spawner.PhantomSpawnerMixin", "world.spawner.WanderingTraderSpawnerMixin", - "world.spawner.WorldEntitySpawnerMixin", "world.storage.MapData_MapInfoMixin", "world.storage.MapDataMixin", "world.storage.SaveHandlerMixin", diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/spawner/WorldEntitySpawnerMixin.java b/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/world/spawner/WorldEntitySpawnerMixin_1_14.java similarity index 93% rename from arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/spawner/WorldEntitySpawnerMixin.java rename to arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/world/spawner/WorldEntitySpawnerMixin_1_14.java index 0cf28ae6..84853627 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/spawner/WorldEntitySpawnerMixin.java +++ b/arclight-forge-1.14/src/main/java/io/izzel/arclight/impl/mixin/v1_14/world/spawner/WorldEntitySpawnerMixin_1_14.java @@ -1,4 +1,4 @@ -package io.izzel.arclight.common.mixin.core.world.spawner; +package io.izzel.arclight.impl.mixin.v1_14.world.spawner; import io.izzel.arclight.common.bridge.world.IWorldWriterBridge; import io.izzel.arclight.common.bridge.world.WorldBridge; @@ -18,7 +18,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import java.util.Random; @Mixin(WorldEntitySpawner.class) -public class WorldEntitySpawnerMixin { +public class WorldEntitySpawnerMixin_1_14 { @Inject(method = "performNaturalSpawning", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/World;addEntity(Lnet/minecraft/entity/Entity;)Z")) private static void arclight$naturalSpawn(EntityClassification p_222263_0_, World worldIn, Chunk p_222263_2_, BlockPos p_222263_3_, CallbackInfo ci) { diff --git a/arclight-forge-1.14/src/main/resources/mixins.arclight.core.1_14.json b/arclight-forge-1.14/src/main/resources/mixins.arclight.core.1_14.json index 30e6642c..f91091b1 100644 --- a/arclight-forge-1.14/src/main/resources/mixins.arclight.core.1_14.json +++ b/arclight-forge-1.14/src/main/resources/mixins.arclight.core.1_14.json @@ -67,6 +67,7 @@ "world.ExplosionMixin_1_14", "world.chunk.ChunkMixin_1_14", "world.dimension.DimensionTypeMixin_1_14", - "world.server.TicketManagerMixin_1_14" + "world.server.TicketManagerMixin_1_14", + "world.spawner.WorldEntitySpawnerMixin_1_14" ] } \ No newline at end of file