From 8cfc27cb70853d50b361e63fb630ac6f4e90067c Mon Sep 17 00:00:00 2001 From: lordlogo2002 Date: Fri, 19 Dec 2025 16:06:12 +0100 Subject: [PATCH] mew let mep spawn --- .../java/net/Chipperfluff/chipi/ChipiMod.java | 111 ++--------------- .../chipi/block/ChipperPortalBlock.java | 24 ++-- .../chipi/client/ChipiClient.java | 1 + .../chipi/client/ModTooltips.java | 63 ++++++++++ .../chipi/entity/ModEntities.java | 26 ++-- .../Chipperfluff/chipi/entity/SpawnLogic.java | 61 ++++++++++ .../chipi/entity/custom/MepEntity.java | 61 ++++++++-- .../chipi/server/ChipiServerEvents.java | 115 ++++++++++++++++++ .../resources/assets/chipi/lang/en_us.json | 2 + .../data/chipi/worldgen/biome/void.json | 14 ++- 10 files changed, 343 insertions(+), 135 deletions(-) create mode 100644 src/main/java/net/Chipperfluff/chipi/client/ModTooltips.java create mode 100644 src/main/java/net/Chipperfluff/chipi/entity/SpawnLogic.java create mode 100644 src/main/java/net/Chipperfluff/chipi/server/ChipiServerEvents.java diff --git a/src/main/java/net/Chipperfluff/chipi/ChipiMod.java b/src/main/java/net/Chipperfluff/chipi/ChipiMod.java index c316572..c26b89a 100644 --- a/src/main/java/net/Chipperfluff/chipi/ChipiMod.java +++ b/src/main/java/net/Chipperfluff/chipi/ChipiMod.java @@ -1,135 +1,42 @@ package net.Chipperfluff.chipi; import net.Chipperfluff.chipi.advancement.ModCriteria; -import net.Chipperfluff.chipi.block.ChipperPortalBlock; import net.Chipperfluff.chipi.block.ModBlocks; -import net.Chipperfluff.chipi.command.ChpCommand; +import net.Chipperfluff.chipi.command.CommandHandler; import net.Chipperfluff.chipi.effect.ChipiBlessingEvents; import net.Chipperfluff.chipi.effect.ChipiHungerHandler; import net.Chipperfluff.chipi.effect.ModEffects; import net.Chipperfluff.chipi.entity.ModEntities; +import net.Chipperfluff.chipi.entity.SpawnLogic; import net.Chipperfluff.chipi.entity.custom.MepEntity; import net.Chipperfluff.chipi.item.ModItemGroups; import net.Chipperfluff.chipi.item.ModItems; -import net.Chipperfluff.chipi.world.gen.ChipiDungeonGenerator; +import net.Chipperfluff.chipi.server.ChipiServerEvents; + import net.fabricmc.api.ModInitializer; -import net.fabricmc.fabric.api.biome.v1.BiomeModifications; -import net.fabricmc.fabric.api.biome.v1.BiomeSelectors; -import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents; import net.fabricmc.fabric.api.object.builder.v1.entity.FabricDefaultAttributeRegistry; -import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.registry.RegistryKey; -import net.minecraft.registry.RegistryKeys; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.structure.StructurePlacementData; -import net.minecraft.structure.StructureTemplate; -import net.minecraft.util.Identifier; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.GameRules; -import net.minecraft.world.World; -import net.minecraft.world.gen.GenerationStep; -import net.Chipperfluff.chipi.command.CommandHandler; public class ChipiMod implements ModInitializer { public static final String MOD_ID = "chipi"; - public static final RegistryKey CHIPI_DIMENSION_KEY = RegistryKey.of(RegistryKeys.WORLD, new Identifier("chipi", "chipi_dimension")); - - private static final Identifier SPAWN_STRUCTURE = new Identifier("chipi", "spawn"); - - private static MinecraftServer SERVER; - @Override public void onInitialize() { ModBlocks.register(); ModItems.register(); ModItemGroups.register(); - ModCriteria.register(); - ModEntities.register(); ModEffects.register(); + ModCriteria.register(); + ChipiBlessingEvents.register(); ChipiHungerHandler.register(); + SpawnLogic.register(); + CommandHandler.register(); FabricDefaultAttributeRegistry.register(ModEntities.MEP, MepEntity.createMepAttributes()); - BiomeModifications.addFeature( - BiomeSelectors.foundInOverworld(), - GenerationStep.Feature.UNDERGROUND_ORES, - RegistryKey.of(RegistryKeys.PLACED_FEATURE, new Identifier("chipi", "chipper_ore")) - ); - - ServerLifecycleEvents.SERVER_STARTED.register(server -> { - SERVER = server; - }); - - ServerTickEvents.END_WORLD_TICK.register(world -> { - if (!world.getRegistryKey().equals(CHIPI_DIMENSION_KEY)) { - return; - } - - for (PlayerEntity player : world.getPlayers()) { - if (player.getBlockY() >= 50) { - continue; - } - - ChipperPortalBlock.teleportToChipiSpawn(world, player); - } - }); - - ServerWorldEvents.LOAD.register((server, world) -> { - if (!world.getRegistryKey().equals(CHIPI_DIMENSION_KEY)) { - return; - } - - world.setTimeOfDay(18000); - world.getGameRules() - .get(GameRules.DO_DAYLIGHT_CYCLE) - .set(false, server); - - SpawnPlacedState state = world.getPersistentStateManager().getOrCreate( - SpawnPlacedState::fromNbt, - SpawnPlacedState::new, - "chipi_spawn" - ); - - if (state.placed) { - return; - } - - StructureTemplate spawnTemplate = world.getStructureTemplateManager().getTemplate(SPAWN_STRUCTURE).orElse(null); - - if (spawnTemplate == null) { - System.err.println("[CHIPI] spawn.nbt not found!"); - return; - } - - BlockPos spawnCenter = new BlockPos(0, 80, 0); - - spawnTemplate.place(world, spawnCenter, spawnCenter, new StructurePlacementData(), world.getRandom(), 2); - - world.setSpawnPos(spawnCenter.up(), 0.0f); - - ChipiDungeonGenerator.generateInitialLayout(world, spawnCenter); - - state.placed = true; - state.markDirty(); - - System.out.println("[CHIPI] Spawn + initial dungeon generated"); - }); - } - - public static ServerWorld getChipiWorld() { - if (SERVER == null) { - return null; - } - - return SERVER.getWorld(CHIPI_DIMENSION_KEY); + ChipiServerEvents.register(); } } diff --git a/src/main/java/net/Chipperfluff/chipi/block/ChipperPortalBlock.java b/src/main/java/net/Chipperfluff/chipi/block/ChipperPortalBlock.java index 0d044d1..4c834ad 100644 --- a/src/main/java/net/Chipperfluff/chipi/block/ChipperPortalBlock.java +++ b/src/main/java/net/Chipperfluff/chipi/block/ChipperPortalBlock.java @@ -52,16 +52,26 @@ public class ChipperPortalBlock extends Block { public static void teleportToChipiSpawn(ServerWorld targetWorld, PlayerEntity player) { BlockPos spawn = resolveSafeSpawn(targetWorld); + player.setVelocity(0.0, 0.0, 0.0); + player.fallDistance = 0.0f; + player.setOnGround(true); + player.teleport( - targetWorld, - spawn.getX() + 0.5, - spawn.getY(), - spawn.getZ() + 0.5, - EnumSet.noneOf(PositionFlag.class), - player.getYaw(), - player.getPitch()); + targetWorld, + spawn.getX() + 0.5, + spawn.getY(), + spawn.getZ() + 0.5, + EnumSet.noneOf(PositionFlag.class), + player.getYaw(), + player.getPitch() + ); + + player.setVelocity(0.0, 0.0, 0.0); + player.fallDistance = 0.0f; + player.setOnGround(true); } + public static BlockPos resolveSafeSpawn(ServerWorld targetWorld) { BlockPos spawn = DEFAULT_SPAWN; BlockPos under = spawn.down(); diff --git a/src/main/java/net/Chipperfluff/chipi/client/ChipiClient.java b/src/main/java/net/Chipperfluff/chipi/client/ChipiClient.java index 2e6a219..3a7984c 100644 --- a/src/main/java/net/Chipperfluff/chipi/client/ChipiClient.java +++ b/src/main/java/net/Chipperfluff/chipi/client/ChipiClient.java @@ -12,5 +12,6 @@ public class ChipiClient implements ClientModInitializer { public void onInitializeClient() { BlockRenderLayerMap.INSTANCE.putBlock(ModBlocks.CHIPPER_PORTAL, RenderLayer.getTranslucent()); ModEntityRenderers.register(); + ModTooltips.register(); } } diff --git a/src/main/java/net/Chipperfluff/chipi/client/ModTooltips.java b/src/main/java/net/Chipperfluff/chipi/client/ModTooltips.java new file mode 100644 index 0000000..fb15412 --- /dev/null +++ b/src/main/java/net/Chipperfluff/chipi/client/ModTooltips.java @@ -0,0 +1,63 @@ +package net.Chipperfluff.chipi.client; + +import net.Chipperfluff.chipi.block.ModBlocks; +import net.Chipperfluff.chipi.item.ModItems; +import net.fabricmc.fabric.api.client.item.v1.ItemTooltipCallback; +import net.minecraft.text.Text; + +public final class ModTooltips { + + private ModTooltips() { + } + + public static void register() { + + ItemTooltipCallback.EVENT.register((stack, context, lines) -> { + + // ===== BLOCK ITEMS ===== + if (stack.isOf(ModBlocks.VOID_BLOCK.asItem())) + lines.add(Text.translatable("tooltip.chipi.void_block")); + + if (stack.isOf(ModBlocks.CHIPPER_FRAME.asItem())) + lines.add(Text.translatable("tooltip.chipi.chipper_frame")); + + if (stack.isOf(ModBlocks.CHIPPER_PORTAL.asItem())) + lines.add(Text.translatable("tooltip.chipi.chipper_portal")); + + if (stack.isOf(ModBlocks.CHIPPER_ORE.asItem())) + lines.add(Text.translatable("tooltip.chipi.chipper_ore")); + + if (stack.isOf(ModBlocks.CHIPPER_ALLOY_BLOCK.asItem())) + lines.add(Text.translatable("tooltip.chipi.chipper_alloy_block")); + + // ===== ITEMS ===== + if (stack.isOf(ModItems.NUT)) + lines.add(Text.translatable("tooltip.chipi.nut")); + + if (stack.isOf(ModItems.RAW_CHIPPER_ORE)) + lines.add(Text.translatable("tooltip.chipi.raw_chipper_ore")); + + if (stack.isOf(ModItems.CHIPPER_INGOT)) + lines.add(Text.translatable("tooltip.chipi.chipper_ingot")); + + if (stack.isOf(ModItems.CHIPPER_ALLOY)) + lines.add(Text.translatable("tooltip.chipi.chipper_alloy")); + + if (stack.isOf(ModItems.MEP_SPAWN_EGG)) + lines.add(Text.translatable("tooltip.chipi.mep_spawn_egg")); + + // ===== ARMOR ===== + if (stack.isOf(ModItems.CHIPPER_HELMET)) + lines.add(Text.translatable("tooltip.chipi.chipper_helmet")); + + if (stack.isOf(ModItems.CHIPPER_CHESTPLATE)) + lines.add(Text.translatable("tooltip.chipi.chipper_chestplate")); + + if (stack.isOf(ModItems.CHIPPER_LEGGINGS)) + lines.add(Text.translatable("tooltip.chipi.chipper_leggings")); + + if (stack.isOf(ModItems.CHIPPER_BOOTS)) + lines.add(Text.translatable("tooltip.chipi.chipper_boots")); + }); + } +} diff --git a/src/main/java/net/Chipperfluff/chipi/entity/ModEntities.java b/src/main/java/net/Chipperfluff/chipi/entity/ModEntities.java index dcbd486..8371741 100644 --- a/src/main/java/net/Chipperfluff/chipi/entity/ModEntities.java +++ b/src/main/java/net/Chipperfluff/chipi/entity/ModEntities.java @@ -1,26 +1,28 @@ package net.Chipperfluff.chipi.entity; -import net.Chipperfluff.chipi.ChipiMod; import net.Chipperfluff.chipi.entity.custom.MepEntity; + import net.fabricmc.fabric.api.object.builder.v1.entity.FabricEntityTypeBuilder; + import net.minecraft.entity.EntityDimensions; +import net.minecraft.entity.SpawnGroup; import net.minecraft.entity.EntityType; import net.minecraft.registry.Registries; import net.minecraft.registry.Registry; import net.minecraft.util.Identifier; -public class ModEntities { +public final class ModEntities { - public static final EntityType MEP = Registry.register( - Registries.ENTITY_TYPE, - new Identifier(ChipiMod.MOD_ID, "mep"), - FabricEntityTypeBuilder.createMob() - .entityFactory(MepEntity::new) - .dimensions(EntityDimensions.fixed(0.6f, 1.95f)) - .build() - ); + public static final EntityType MEP = + Registry.register( + Registries.ENTITY_TYPE, + new Identifier("chipi", "mep"), + FabricEntityTypeBuilder + .create(SpawnGroup.CREATURE, MepEntity::new) + .dimensions(EntityDimensions.fixed(0.6f, 1.95f)) + .build() + ); - public static void register() { - // called from mod init + private ModEntities() { } } diff --git a/src/main/java/net/Chipperfluff/chipi/entity/SpawnLogic.java b/src/main/java/net/Chipperfluff/chipi/entity/SpawnLogic.java new file mode 100644 index 0000000..990e5af --- /dev/null +++ b/src/main/java/net/Chipperfluff/chipi/entity/SpawnLogic.java @@ -0,0 +1,61 @@ +package net.Chipperfluff.chipi.entity; + +import net.fabricmc.fabric.api.biome.v1.BiomeModifications; +import net.fabricmc.fabric.api.biome.v1.BiomeSelectors; + +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.SpawnGroup; +import net.minecraft.entity.SpawnReason; +import net.minecraft.entity.SpawnRestriction; +import net.minecraft.entity.mob.MobEntity; +import net.minecraft.registry.RegistryKey; +import net.minecraft.registry.RegistryKeys; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.random.Random; +import net.minecraft.world.Heightmap; +import net.minecraft.world.ServerWorldAccess; +import net.minecraft.world.biome.Biome; + +public final class SpawnLogic { + + private static final RegistryKey VOID_BIOME = + RegistryKey.of(RegistryKeys.BIOME, new Identifier("chipi", "void")); + + private SpawnLogic() { + } + + public static void register() { + + BiomeModifications.addSpawn( + BiomeSelectors.includeByKey(VOID_BIOME), + SpawnGroup.MONSTER, + ModEntities.MEP, + 10, + 1, + 4 + ); + + SpawnRestriction.register( + ModEntities.MEP, + SpawnRestriction.Location.ON_GROUND, + Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, + SpawnLogic::canSpawn + ); + } + + private static boolean canSpawn(EntityType type, ServerWorldAccess world, SpawnReason reason, BlockPos pos, Random random) { + int y = pos.getY(); + if (y < 87 || y > 90) return false; + if (pos.getZ() < 18) return false; + + BlockState below = world.getBlockState(pos.down()); + boolean can_spawn = below.isOf(Blocks.POLISHED_BLACKSTONE_BRICKS); + + System.out.println("[MEP ENTITY] spawn check pos=" + pos + " below=" + below.getBlock()); + + return can_spawn; + } +} diff --git a/src/main/java/net/Chipperfluff/chipi/entity/custom/MepEntity.java b/src/main/java/net/Chipperfluff/chipi/entity/custom/MepEntity.java index 204c8f1..07846d1 100644 --- a/src/main/java/net/Chipperfluff/chipi/entity/custom/MepEntity.java +++ b/src/main/java/net/Chipperfluff/chipi/entity/custom/MepEntity.java @@ -22,7 +22,10 @@ import net.minecraft.world.World; public class MepEntity extends PathAwareEntity { + private static final int FORGET_TARGET_AFTER_TICKS = 100; + private boolean angryAtPlayer = false; + private int ticksSinceLastSeen = 0; public MepEntity(EntityType entityType, World world) { super(entityType, world); @@ -42,7 +45,7 @@ public class MepEntity extends PathAwareEntity { this, PlayerEntity.class, true, - target -> target instanceof PlayerEntity player && (angryAtPlayer || !isPlayerProtected(player)) + target -> target instanceof PlayerEntity player && !isPlayerProtected(player) ) ); } @@ -51,13 +54,15 @@ public class MepEntity extends PathAwareEntity { return PathAwareEntity.createMobAttributes() .add(EntityAttributes.GENERIC_MAX_HEALTH, 20.0) .add(EntityAttributes.GENERIC_ATTACK_DAMAGE, 4.0) - .add(EntityAttributes.GENERIC_MOVEMENT_SPEED, 0.25); + .add(EntityAttributes.GENERIC_MOVEMENT_SPEED, 0.25) + .add(EntityAttributes.GENERIC_FOLLOW_RANGE, 32.0); } @Override public boolean damage(DamageSource source, float amount) { if (source.getAttacker() instanceof PlayerEntity) { angryAtPlayer = true; + ticksSinceLastSeen = 0; } return super.damage(source, amount); } @@ -68,18 +73,39 @@ public class MepEntity extends PathAwareEntity { LivingEntity target = this.getTarget(); - if (angryAtPlayer) { - if (!(target instanceof PlayerEntity) || !this.canSee(target)) { - angryAtPlayer = false; - this.setTarget(null); - } + if (!(target instanceof PlayerEntity player)) { + ticksSinceLastSeen = 0; + angryAtPlayer = false; return; } - if (target instanceof PlayerEntity player && isPlayerProtected(player)) { - this.setTarget(null); - this.getNavigation().stop(); + // Protected players instantly cancel targeting + if (isPlayerProtected(player)) { + clearTarget(); + return; } + + if (this.canSee(player)) { + ticksSinceLastSeen = 0; + angryAtPlayer = true; + this.getNavigation().startMovingTo(player, 1.2D); + } else { + ticksSinceLastSeen++; + + // Keep chasing for a while even without LOS + if (ticksSinceLastSeen <= FORGET_TARGET_AFTER_TICKS) { + this.getNavigation().startMovingTo(player, 1.2D); + } else { + clearTarget(); + } + } + } + + private void clearTarget() { + angryAtPlayer = false; + ticksSinceLastSeen = 0; + this.setTarget(null); + this.getNavigation().stop(); } private static boolean isPlayerProtected(PlayerEntity player) { @@ -90,6 +116,19 @@ public class MepEntity extends PathAwareEntity { return false; } - return state.getBlock() instanceof StairsBlock || state.getBlock() instanceof SlabBlock; + return state.getBlock() instanceof StairsBlock + || state.getBlock() instanceof SlabBlock; + } + + // === Despawn prevention === + + @Override + public boolean cannotDespawn() { + return true; + } + + @Override + public boolean canImmediatelyDespawn(double distanceSquared) { + return false; } } diff --git a/src/main/java/net/Chipperfluff/chipi/server/ChipiServerEvents.java b/src/main/java/net/Chipperfluff/chipi/server/ChipiServerEvents.java new file mode 100644 index 0000000..1b10c1f --- /dev/null +++ b/src/main/java/net/Chipperfluff/chipi/server/ChipiServerEvents.java @@ -0,0 +1,115 @@ +package net.Chipperfluff.chipi.server; + +import net.Chipperfluff.chipi.block.ChipperPortalBlock; +import net.Chipperfluff.chipi.world.gen.ChipiDungeonGenerator; +import net.Chipperfluff.chipi.SpawnPlacedState; + +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents; + +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.registry.RegistryKey; +import net.minecraft.registry.RegistryKeys; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.world.ServerWorld; +import net.minecraft.structure.StructurePlacementData; +import net.minecraft.structure.StructureTemplate; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.GameRules; +import net.minecraft.world.World; + +public final class ChipiServerEvents { + + public static final RegistryKey CHIPI_DIMENSION_KEY = + RegistryKey.of(RegistryKeys.WORLD, new Identifier("chipi", "chipi_dimension")); + + private static final Identifier SPAWN_STRUCTURE = + new Identifier("chipi", "spawn"); + + private static MinecraftServer SERVER; + + private ChipiServerEvents() {} + + public static void register() { + + ServerLifecycleEvents.SERVER_STARTED.register(server -> { + SERVER = server; + }); + + ServerTickEvents.END_WORLD_TICK.register(ChipiServerEvents::handleVoidFailsafe); + + ServerWorldEvents.LOAD.register(ChipiServerEvents::onWorldLoad); + } + + // ============================================================ + // Tick logic + // ============================================================ + private static void handleVoidFailsafe(ServerWorld world) { + if (!world.getRegistryKey().equals(CHIPI_DIMENSION_KEY)) return; + + for (PlayerEntity player : world.getPlayers()) { + if (player.getBlockY() >= 50) continue; + ChipperPortalBlock.teleportToChipiSpawn(world, player); + } + } + + // ============================================================ + // World init + // ============================================================ + private static void onWorldLoad(MinecraftServer server, ServerWorld world) { + if (!world.getRegistryKey().equals(CHIPI_DIMENSION_KEY)) return; + + world.setTimeOfDay(18000); + world.getGameRules() + .get(GameRules.DO_DAYLIGHT_CYCLE) + .set(false, server); + + SpawnPlacedState state = world.getPersistentStateManager().getOrCreate( + SpawnPlacedState::fromNbt, + SpawnPlacedState::new, + "chipi_spawn" + ); + + if (state.placed) return; + + StructureTemplate spawnTemplate = + world.getStructureTemplateManager() + .getTemplate(SPAWN_STRUCTURE) + .orElse(null); + + if (spawnTemplate == null) { + System.err.println("[CHIPI] spawn.nbt not found!"); + return; + } + + BlockPos spawnCenter = new BlockPos(0, 80, 0); + + spawnTemplate.place( + world, + spawnCenter, + spawnCenter, + new StructurePlacementData(), + world.getRandom(), + 2 + ); + + world.setSpawnPos(spawnCenter.up(), 0.0f); + + ChipiDungeonGenerator.generateInitialLayout(world, spawnCenter); + + state.placed = true; + state.markDirty(); + + System.out.println("[CHIPI] Spawn + initial dungeon generated"); + } + + // ============================================================ + // Access + // ============================================================ + public static ServerWorld getChipiWorld() { + if (SERVER == null) return null; + return SERVER.getWorld(CHIPI_DIMENSION_KEY); + } +} diff --git a/src/main/resources/assets/chipi/lang/en_us.json b/src/main/resources/assets/chipi/lang/en_us.json index e049bd6..eaa6ef9 100644 --- a/src/main/resources/assets/chipi/lang/en_us.json +++ b/src/main/resources/assets/chipi/lang/en_us.json @@ -6,6 +6,8 @@ "effect.chipi.chipi_blessing": "Chipi's Blessing", + "entity.chipi.mep": "Merp :3", + "block.chipi.void_block": "Void Block", "block.chipi.chipper_frame": "Chipper Frame", "block.chipi.chipper_portal": "Chipper Portal", diff --git a/src/main/resources/data/chipi/worldgen/biome/void.json b/src/main/resources/data/chipi/worldgen/biome/void.json index cb6c2a2..5f29828 100644 --- a/src/main/resources/data/chipi/worldgen/biome/void.json +++ b/src/main/resources/data/chipi/worldgen/biome/void.json @@ -3,7 +3,7 @@ "downfall": 0, "has_precipitation": false, "temperature_modifier": "frozen", - "creature_spawn_probability": 0, + "creature_spawn_probability": 0.1, "effects": { "sky_color": 0, "fog_color": 0, @@ -13,8 +13,16 @@ "foliage_color": 0, "grass_color_modifier": "none" }, - "spawners": {}, + "spawners": { + "monster": [], + "creature": [], + "ambient": [], + "axolotls": [], + "underground_water_creature": [], + "water_creature": [], + "water_ambient": [] + }, "spawn_costs": {}, "carvers": {}, "features": [] -} \ No newline at end of file +}