diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/WorldBridge.java b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/WorldBridge.java index 9b13b644..52bb64fd 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/WorldBridge.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/bridge/core/world/WorldBridge.java @@ -1,11 +1,13 @@ package io.izzel.arclight.common.bridge.core.world; +import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceKey; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.dimension.LevelStem; import org.bukkit.craftbukkit.v.CraftServer; import org.bukkit.craftbukkit.v.CraftWorld; +import org.bukkit.entity.SpawnCategory; import org.bukkit.generator.ChunkGenerator; import org.spigotmc.SpigotWorldConfig; @@ -29,17 +31,7 @@ public interface WorldBridge extends IWorldWriterBridge, IWorldBridge { SpigotWorldConfig bridge$spigotConfig(); - long bridge$ticksPerAnimalSpawns(); - - long bridge$ticksPerMonsterSpawns(); - - long bridge$ticksPerWaterSpawns(); - - long bridge$ticksPerAmbientSpawns(); - - long bridge$ticksPerWaterAmbientSpawns(); - - long bridge$ticksPerWaterUndergroundSpawns(); + Object2LongOpenHashMap bridge$ticksPerSpawnCategory(); ResourceKey bridge$getTypeKey(); } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/ServerChunkCacheMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/ServerChunkCacheMixin.java index f4d979e5..8aba88b3 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/ServerChunkCacheMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/server/level/ServerChunkCacheMixin.java @@ -16,6 +16,7 @@ import net.minecraft.world.level.GameRules; import net.minecraft.world.level.chunk.ChunkGenerator; import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.storage.LevelData; +import org.bukkit.entity.SpawnCategory; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -95,7 +96,7 @@ public abstract class ServerChunkCacheMixin implements ServerChunkProviderBridge @Redirect(method = "tickChunks", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/storage/LevelData;getGameTime()J")) private long arclight$ticksPer(LevelData worldInfo) { long gameTime = worldInfo.getGameTime(); - long ticksPer = ((WorldBridge) this.level).bridge$ticksPerAnimalSpawns(); + long ticksPer = ((WorldBridge) this.level).bridge$ticksPerSpawnCategory().getLong(SpawnCategory.ANIMAL); return (ticksPer != 0L && gameTime % ticksPer == 0) ? 0 : 1; } diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/EntityMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/EntityMixin.java index 96e8aed1..7d1cc24f 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/EntityMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/entity/EntityMixin.java @@ -873,6 +873,11 @@ public abstract class EntityMixin implements InternalEntityBridge, EntityBridge, return null; } else { ServerLevel world = ((PortalInfoBridge) portalinfo).bridge$getWorld() == null ? server : ((PortalInfoBridge) portalinfo).bridge$getWorld(); + if (world == server) { + this.moveTo(portalinfo.pos.x, portalinfo.pos.y, portalinfo.pos.z, portalinfo.yRot, this.getXRot()); + this.setDeltaMovement(portalinfo.speed); + return (Entity) (Object) this; + } this.unRide(); Entity transportedEntity = teleporter.placeEntity((Entity) (Object) this, (ServerLevel) this.level, server, this.getYRot(), spawnPortal -> { //Forge: Start vanilla logic this.level.getProfiler().popPush("reloading"); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/LevelMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/LevelMixin.java index ed38d4f5..b0f3b9d0 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/LevelMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/level/LevelMixin.java @@ -9,6 +9,7 @@ import io.izzel.arclight.common.bridge.core.world.server.ServerWorldBridge; import io.izzel.arclight.common.mod.server.ArclightServer; import io.izzel.arclight.common.mod.server.world.WrappedWorlds; import io.izzel.arclight.common.mod.util.ArclightCaptures; +import it.unimi.dsi.fastutil.objects.Object2LongOpenHashMap; import net.minecraft.core.BlockPos; import net.minecraft.core.Registry; import net.minecraft.resources.ResourceKey; @@ -42,6 +43,8 @@ import org.bukkit.craftbukkit.v.generator.CraftWorldInfo; import org.bukkit.craftbukkit.v.generator.CustomChunkGenerator; import org.bukkit.craftbukkit.v.generator.CustomWorldChunkManager; import org.bukkit.craftbukkit.v.util.CraftNamespacedKey; +import org.bukkit.craftbukkit.v.util.CraftSpawnCategory; +import org.bukkit.entity.SpawnCategory; import org.bukkit.event.block.BlockPhysicsEvent; import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.world.GenericGameEvent; @@ -81,12 +84,7 @@ public abstract class LevelMixin implements WorldBridge, LevelWriter { protected CraftWorld world; public boolean pvpMode; public boolean keepSpawnInMemory = true; - public long ticksPerAnimalSpawns; - public long ticksPerMonsterSpawns; - public long ticksPerWaterSpawns; - public long ticksPerWaterAmbientSpawns; - public long ticksPerWaterUndergroundCreatureSpawns; - public long ticksPerAmbientSpawns; + public final Object2LongOpenHashMap ticksPerSpawnCategory = new Object2LongOpenHashMap<>(); public boolean populating; public org.bukkit.generator.ChunkGenerator generator; protected org.bukkit.World.Environment environment; @@ -111,42 +109,16 @@ public abstract class LevelMixin implements WorldBridge, LevelWriter { @Inject(method = "(Lnet/minecraft/world/level/storage/WritableLevelData;Lnet/minecraft/resources/ResourceKey;Lnet/minecraft/world/level/dimension/DimensionType;Ljava/util/function/Supplier;ZZJ)V", at = @At("RETURN")) private void arclight$init(WritableLevelData info, ResourceKey dimension, DimensionType dimType, Supplier profiler, boolean isRemote, boolean isDebug, long seed, CallbackInfo ci) { ((WorldBorderBridge) this.worldBorder).bridge$setWorld((Level) (Object) this); - this.ticksPerAnimalSpawns = this.getCraftServer().getTicksPerAnimalSpawns(); - this.ticksPerMonsterSpawns = this.getCraftServer().getTicksPerMonsterSpawns(); - this.ticksPerWaterSpawns = this.getCraftServer().getTicksPerWaterSpawns(); - this.ticksPerWaterAmbientSpawns = this.getCraftServer().getTicksPerWaterAmbientSpawns(); - this.ticksPerWaterUndergroundCreatureSpawns = this.getCraftServer().getTicksPerWaterUndergroundCreatureSpawns(); - this.ticksPerAmbientSpawns = this.getCraftServer().getTicksPerAmbientSpawns(); + for (SpawnCategory spawnCategory : SpawnCategory.values()) { + if (CraftSpawnCategory.isValidForLimits(spawnCategory)) { + this.ticksPerSpawnCategory.put(spawnCategory, this.getCraftServer().getTicksPerSpawns(spawnCategory)); + } + } } @Override - public long bridge$ticksPerAnimalSpawns() { - return ticksPerAnimalSpawns; - } - - @Override - public long bridge$ticksPerMonsterSpawns() { - return ticksPerMonsterSpawns; - } - - @Override - public long bridge$ticksPerWaterSpawns() { - return ticksPerWaterSpawns; - } - - @Override - public long bridge$ticksPerAmbientSpawns() { - return ticksPerAmbientSpawns; - } - - @Override - public long bridge$ticksPerWaterAmbientSpawns() { - return ticksPerWaterAmbientSpawns; - } - - @Override - public long bridge$ticksPerWaterUndergroundSpawns() { - return ticksPerWaterUndergroundCreatureSpawns; + public Object2LongOpenHashMap bridge$ticksPerSpawnCategory() { + return this.ticksPerSpawnCategory; } public abstract ResourceKey getTypeKey(); diff --git a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/spawner/WorldEntitySpawnerMixin.java b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/spawner/WorldEntitySpawnerMixin.java index 692441df..c910df89 100644 --- a/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/spawner/WorldEntitySpawnerMixin.java +++ b/arclight-common/src/main/java/io/izzel/arclight/common/mixin/core/world/spawner/WorldEntitySpawnerMixin.java @@ -14,6 +14,8 @@ import net.minecraft.world.level.biome.Biome; import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.storage.LevelData; +import org.bukkit.craftbukkit.v.util.CraftSpawnCategory; +import org.bukkit.entity.SpawnCategory; import org.bukkit.event.entity.CreatureSpawnEvent; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -53,40 +55,13 @@ public abstract class WorldEntitySpawnerMixin { world.getProfiler().push("spawner"); MobCategory[] classifications = SPAWNING_CATEGORIES; LevelData worldInfo = world.getLevelData(); - boolean spawnAnimalThisTick = ((WorldBridge) world).bridge$ticksPerAnimalSpawns() != 0L && worldInfo.getGameTime() % ((WorldBridge) world).bridge$ticksPerAnimalSpawns() == 0L; - boolean spawnMonsterThisTick = ((WorldBridge) world).bridge$ticksPerMonsterSpawns() != 0L && worldInfo.getGameTime() % ((WorldBridge) world).bridge$ticksPerMonsterSpawns() == 0L; - boolean spawnWaterThisTick = ((WorldBridge) world).bridge$ticksPerWaterSpawns() != 0L && worldInfo.getGameTime() % ((WorldBridge) world).bridge$ticksPerWaterSpawns() == 0L; - boolean spawnAmbientThisTick = ((WorldBridge) world).bridge$ticksPerAmbientSpawns() != 0L && worldInfo.getGameTime() % ((WorldBridge) world).bridge$ticksPerAmbientSpawns() == 0L; - boolean spawnWaterAmbientThisTick = ((WorldBridge) world).bridge$ticksPerWaterAmbientSpawns() != 0L && worldInfo.getGameTime() % ((WorldBridge) world).bridge$ticksPerWaterAmbientSpawns() == 0L; - boolean spawnWaterUndergroundThisTick = ((WorldBridge) world).bridge$ticksPerWaterUndergroundSpawns() != 0L && worldInfo.getGameTime() % ((WorldBridge) world).bridge$ticksPerWaterUndergroundSpawns() == 0L; for (MobCategory classification : classifications) { boolean spawnThisTick = true; int limit = classification.getMaxInstancesPerChunk(); - switch (classification) { - case MONSTER -> { - spawnThisTick = spawnMonsterThisTick; - limit = ((WorldBridge) world).bridge$getWorld().getMonsterSpawnLimit(); - } - case CREATURE -> { - spawnThisTick = spawnAnimalThisTick; - limit = ((WorldBridge) world).bridge$getWorld().getAnimalSpawnLimit(); - } - case UNDERGROUND_WATER_CREATURE -> { - spawnThisTick = spawnWaterUndergroundThisTick; - limit = ((WorldBridge) world).bridge$getWorld().getWaterUndergroundCreatureSpawnLimit(); - } - case WATER_CREATURE -> { - spawnThisTick = spawnWaterThisTick; - limit = ((WorldBridge) world).bridge$getWorld().getWaterAnimalSpawnLimit(); - } - case AMBIENT -> { - spawnThisTick = spawnAmbientThisTick; - limit = ((WorldBridge) world).bridge$getWorld().getAmbientSpawnLimit(); - } - case WATER_AMBIENT -> { - spawnThisTick = spawnWaterAmbientThisTick; - limit = ((WorldBridge) world).bridge$getWorld().getWaterAmbientSpawnLimit(); - } + SpawnCategory spawnCategory = CraftSpawnCategory.toBukkit(classification); + if (CraftSpawnCategory.isValidForLimits(spawnCategory)) { + spawnThisTick = ((WorldBridge) world).bridge$ticksPerSpawnCategory().getLong(spawnCategory) != 0 && worldInfo.getGameTime() % ((WorldBridge) world).bridge$ticksPerSpawnCategory().getLong(spawnCategory) == 0; + limit = ((WorldBridge) world).bridge$getWorld().getSpawnLimit(spawnCategory); } if (spawnThisTick) { if (limit != 0) {