Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import net.minecraft.server.level.ServerLevel;
- import net.minecraft.world.entity.Entity;
- import net.minecraft.world.entity.animal.Wolf;
- import net.minecraft.world.level.ChunkPos;
- import net.minecraftforge.event.entity.EntityLeaveLevelEvent;
- import net.minecraftforge.event.entity.living.LivingEvent;
- import net.minecraftforge.event.server.ServerStartedEvent;
- import net.minecraftforge.event.server.ServerStoppingEvent;
- import net.minecraftforge.eventbus.api.SubscribeEvent;
- import net.minecraftforge.fml.common.Mod;
- import java.util.*;
- @Mod(Constants.MOD_ID) @Mod.EventBusSubscriber
- public class ExampleMod {
- public ExampleMod() {
- CommonClass.init();
- }
- // wolf UUID -> the last known ChunkPos of the wolf
- public static final HashMap<UUID, ChunkPos> WOLF_POSITIONS = new HashMap<>();
- // wolf UUID -> the set of chunks the wolf is force-loading
- public static final HashMap<UUID, Set<ChunkPos>> WOLF_CHUNKS = new HashMap<>();
- // chunk -> the set of wolves forcibly loading the chunk
- public static final HashMap<ChunkPos, Set<UUID>> CHUNK_WOLVES = new HashMap<>();
- @SubscribeEvent
- public static void onLivingTick(LivingEvent.LivingTickEvent event) {
- if (event.getEntity() instanceof Wolf wolf && !wolf.level().isClientSide()) {
- ExampleMod.onWolfTick(wolf);
- }
- }
- @SubscribeEvent
- public static void onEntityLeaveWorld(EntityLeaveLevelEvent event) {
- if (event.getEntity() instanceof Wolf wolf && !wolf.level().isClientSide()) {
- ExampleMod.onWolfRemoved(wolf);
- }
- }
- @SubscribeEvent
- public static void onWorldLoad(ServerStartedEvent event) {
- event.getServer().getAllLevels().forEach(level -> {
- ExampleMod.initializeForWorld(level);
- });
- }
- public static void initializeForWorld(ServerLevel level) {
- for (Entity entity : level.getAllEntities()) {
- if (!(entity instanceof Wolf wolf)) return;
- Set<ChunkPos> chunks = getChunksAroundWolf(wolf);
- forceLoadChunks(level, chunks);
- WOLF_CHUNKS.put(wolf.getUUID(), chunks);
- }
- }
- @SubscribeEvent
- public static void onWorldUnload(ServerStoppingEvent event) {
- event.getServer().getAllLevels().forEach(level -> {
- ExampleMod.cleanupForWorld(level);
- });
- }
- public static void cleanupForWorld(ServerLevel level) {
- Set<UUID> wolvesToRemove = new HashSet<>();
- for (Map.Entry<UUID, Set<ChunkPos>> entry : WOLF_CHUNKS.entrySet()) {
- UUID wolfId = entry.getKey();
- Set<ChunkPos> chunks = entry.getValue();
- Entity entity = level.getEntity(wolfId);
- if (entity instanceof Wolf && !chunks.isEmpty()) {
- wolvesToRemove.add(wolfId);
- for (ChunkPos chunk : chunks) {
- try {
- level.setChunkForced(chunk.x, chunk.z, false);
- }
- catch (Exception e) {
- System.err.println("Failed to unforce chunk " + chunk + ": " + e.getMessage());
- }
- }
- }
- }
- for (UUID wolfId : wolvesToRemove) {
- Set<ChunkPos> chunks = WOLF_CHUNKS.remove(wolfId);
- WOLF_POSITIONS.remove(wolfId);
- if (chunks != null) {
- for (ChunkPos chunk : chunks) {
- Set<UUID> wolves = CHUNK_WOLVES.get(chunk);
- if (wolves != null) {
- wolves.remove(wolfId);
- if (wolves.isEmpty()) {
- CHUNK_WOLVES.remove(chunk);
- }
- }
- }
- }
- }
- }
- private static Set<ChunkPos> getChunksAroundWolf(Wolf wolf) {
- ChunkPos center = new ChunkPos(wolf.blockPosition());
- Set<ChunkPos> chunkSet = new HashSet<>();
- for (int x = -1; x <= 1; ++x) {
- for (int z = -1; z <= 1; ++z) {
- chunkSet.add(new ChunkPos(center.x + x, center.z + z));
- }
- }
- return chunkSet;
- }
- private static void forceLoadChunks(ServerLevel level, Set<ChunkPos> chunks) {
- for (ChunkPos chunk : chunks) {
- level.setChunkForced(chunk.x, chunk.z, true);
- }
- }
- public static void onWolfTick(Wolf wolf) {
- UUID wolfId = wolf.getUUID();
- ChunkPos currentChunk = new ChunkPos(wolf.blockPosition());
- ChunkPos lastKnownChunk = WOLF_POSITIONS.get(wolfId);
- if (lastKnownChunk == null || !lastKnownChunk.equals(currentChunk)) {
- updateWolfChunkLoading(wolf, currentChunk, lastKnownChunk);
- WOLF_POSITIONS.put(wolfId, currentChunk);
- }
- }
- private static void updateWolfChunkLoading(Wolf wolf, ChunkPos newCenter, ChunkPos oldCenter) {
- UUID wolfId = wolf.getUUID();
- ServerLevel level = (ServerLevel) wolf.level();
- Set<ChunkPos> newChunks = getChunksAroundWolf(wolf);
- Set<ChunkPos> oldChunks = WOLF_CHUNKS.getOrDefault(wolfId, new HashSet<>());
- Set<ChunkPos> chunksToUnload = new HashSet<>(oldChunks);
- chunksToUnload.removeAll(newChunks);
- Set<ChunkPos> chunksToLoad = new HashSet<>(newChunks);
- chunksToLoad.removeAll(oldChunks);
- for (ChunkPos chunk : chunksToUnload) {
- removeWolfFromChunk(wolfId, chunk);
- if (!CHUNK_WOLVES.containsKey(chunk) || CHUNK_WOLVES.get(chunk).isEmpty()) {
- level.setChunkForced(chunk.x, chunk.z, false);
- CHUNK_WOLVES.remove(chunk);
- }
- }
- for (ChunkPos chunk : chunksToLoad) {
- addWolfToChunk(wolfId, chunk);
- level.setChunkForced(chunk.x, chunk.z, true);
- }
- WOLF_CHUNKS.put(wolfId, newChunks);
- }
- private static void addWolfToChunk(UUID wolfId, ChunkPos chunk) {
- CHUNK_WOLVES.computeIfAbsent(chunk, k -> new HashSet<>()).add(wolfId);
- }
- private static void removeWolfFromChunk(UUID wolfId, ChunkPos chunk) {
- Set<UUID> wolves = CHUNK_WOLVES.get(chunk);
- if (wolves != null) {
- wolves.remove(wolfId);
- }
- }
- public static void onWolfRemoved(Wolf wolf) {
- UUID wolfId = wolf.getUUID();
- Set<ChunkPos> chunks = WOLF_CHUNKS.remove(wolfId);
- WOLF_POSITIONS.remove(wolfId);
- if (chunks != null) {
- ServerLevel level = (ServerLevel) wolf.level();
- for (ChunkPos chunk : chunks) {
- removeWolfFromChunk(wolfId, chunk);
- if (!CHUNK_WOLVES.containsKey(chunk) || CHUNK_WOLVES.get(chunk).isEmpty()) {
- level.setChunkForced(chunk.x, chunk.z, false);
- CHUNK_WOLVES.remove(chunk);
- }
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment