Skip to content

Commit

Permalink
Add spawn_limiter attachment for mob spawners
Browse files Browse the repository at this point in the history
  • Loading branch information
Gegy committed Nov 11, 2024
1 parent c4de1ee commit 76b0207
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/main/java/com/lovetropics/minigames/LoveTropics.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import com.lovetropics.minigames.common.core.diguise.PlayerDisguise;
import com.lovetropics.minigames.common.core.dimension.RuntimeDimensions;
import com.lovetropics.minigames.common.core.entity.MinigameEntities;
import com.lovetropics.minigames.common.core.extension.LimitedSpawnerAttachment;
import com.lovetropics.minigames.common.core.game.IGameManager;
import com.lovetropics.minigames.common.core.game.behavior.GameBehaviorTypes;
import com.lovetropics.minigames.common.core.game.behavior.action.ActionTargetTypes;
Expand Down Expand Up @@ -167,6 +168,7 @@ public LoveTropics(IEventBus modBus, ModContainer modContainer) {
DriftwoodRider.ATTACHMENT_TYPES.register(modBus);
PlayerDisguise.ATTACHMENT_TYPES.register(modBus);
ChatChannelStore.ATTACHMENT_TYPES.register(modBus);
LimitedSpawnerAttachment.ATTACHMENT_TYPES.register(modBus);
SoundRegistry.REGISTER.register(modBus);
MinigameDataComponents.REGISTER.register(modBus);
BiodiversityBlitz.DATA_COMPONENTS.register(modBus);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package com.lovetropics.minigames.common.core.extension;

import com.lovetropics.minigames.LoveTropics;
import com.lovetropics.minigames.mixin.BaseSpawnerAccessor;
import com.mojang.datafixers.util.Either;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.BlockPos;
import net.minecraft.core.UUIDUtil;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.BaseSpawner;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.attachment.AttachmentType;
import net.neoforged.neoforge.event.entity.living.FinalizeSpawnEvent;
import net.neoforged.neoforge.event.entity.living.MobSpawnEvent;
import net.neoforged.neoforge.registries.DeferredRegister;
import net.neoforged.neoforge.registries.NeoForgeRegistries;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Optional;
import java.util.Set;
import java.util.UUID;
import java.util.function.Supplier;

@EventBusSubscriber(modid = LoveTropics.ID)
public class LimitedSpawnerAttachment {
public static final DeferredRegister<AttachmentType<?>> ATTACHMENT_TYPES = DeferredRegister.create(NeoForgeRegistries.ATTACHMENT_TYPES, LoveTropics.ID);

public static final Codec<LimitedSpawnerAttachment> CODEC = RecordCodecBuilder.create(i -> i.group(
Codec.INT.fieldOf("max_count").forGetter(a -> a.maxCount),
UUIDUtil.CODEC_SET.optionalFieldOf("spawned_mobs", Set.of()).forGetter(a -> a.spawnedMobs)
).apply(i, (maxCount, spawnedMobs) -> {
LimitedSpawnerAttachment attachment = new LimitedSpawnerAttachment(maxCount);
attachment.spawnedMobs.addAll(spawnedMobs);
return attachment;
}));

public static final Supplier<AttachmentType<LimitedSpawnerAttachment>> ATTACHMENT = ATTACHMENT_TYPES.register(
"limited_spawner",
() -> AttachmentType.<LimitedSpawnerAttachment>builder(() -> {
throw new IllegalStateException("Cannot create default limited_spawner attachment");
}).serialize(CODEC).build()
);

private final int maxCount;
private final Set<UUID> spawnedMobs = new HashSet<>();

public LimitedSpawnerAttachment(int maxCount) {
this.maxCount = maxCount;
}

@SubscribeEvent
public static void onCheckSpawn(MobSpawnEvent.PositionCheck event) {
BaseSpawner spawner = event.getSpawner();
if (spawner == null || spawner.getOwner() == null) {
return;
}
Either<BlockEntity, Entity> owner = spawner.getOwner();
getAttachment(owner).ifPresent(attachment -> {
ServerLevel level = event.getLevel().getLevel();
if (!attachment.checkCanSpawn(level)) {
BlockPos pos = owner.map(BlockEntity::getBlockPos, Entity::blockPosition);
((BaseSpawnerAccessor) spawner).invokeDelay(level, pos);
event.setResult(MobSpawnEvent.PositionCheck.Result.FAIL);
}
});
}

@SubscribeEvent
public static void onFinalizeSpawn(FinalizeSpawnEvent event) {
Either<BlockEntity, Entity> spawner = event.getSpawner();
if (spawner != null) {
getAttachment(spawner).ifPresent(attachment -> attachment.spawnedMobs.add(event.getEntity().getUUID()));
}
}

private static Optional<LimitedSpawnerAttachment> getAttachment(Either<BlockEntity, Entity> spawner) {
return spawner.map(
blockEntity -> blockEntity.getExistingData(ATTACHMENT),
entity -> entity.getExistingData(ATTACHMENT)
);
}

private boolean checkCanSpawn(ServerLevel level) {
pruneDeadMobs(level);
return spawnedMobs.size() < maxCount;
}

private void pruneDeadMobs(ServerLevel level) {
Iterator<UUID> iterator = spawnedMobs.iterator();
while (iterator.hasNext()) {
Entity mob = level.getEntity(iterator.next());
if (mob == null || !mob.isAlive()) {
iterator.remove();
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
@FieldsAreNonnullByDefault
package com.lovetropics.minigames.common.core.extension;

import net.minecraft.FieldsAreNonnullByDefault;
import net.minecraft.MethodsReturnNonnullByDefault;

import javax.annotation.ParametersAreNonnullByDefault;
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.lovetropics.minigames.mixin;

import net.minecraft.core.BlockPos;
import net.minecraft.world.level.BaseSpawner;
import net.minecraft.world.level.Level;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;

@Mixin(BaseSpawner.class)
public interface BaseSpawnerAccessor {
@Invoker("delay")
void invokeDelay(Level level, BlockPos pos);
}
1 change: 1 addition & 0 deletions src/main/resources/ltminigames.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"compatibilityLevel": "JAVA_21",
"plugin": "com.lovetropics.minigames.mixin.LTMixinPlugin",
"mixins": [
"BaseSpawnerAccessor",
"ChunkStorageMixin",
"CommonHooksMixin",
"DataCommandsMixin",
Expand Down

0 comments on commit 76b0207

Please sign in to comment.