return cache;
}
- public void close() {
+ public void clear() {
cache.clear();
}
import com.irtimaled.bbor.common.messages.RemoveBoundingBox;
import com.irtimaled.bbor.common.models.BoundingBox;
import com.irtimaled.bbor.common.models.BoundingBoxMobSpawner;
-import com.irtimaled.bbor.common.models.BoundingBoxVillage;
import com.irtimaled.bbor.common.models.WorldData;
-import com.irtimaled.bbor.config.ConfigManager;
import io.netty.channel.local.LocalAddress;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.network.play.server.SPacketCustomPayload;
import net.minecraft.util.math.BlockPos;
-import net.minecraft.village.Village;
+import net.minecraft.village.VillageCollection;
import net.minecraft.world.World;
+import net.minecraft.world.WorldServer;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.IChunkProvider;
import net.minecraft.world.dimension.DimensionType;
public class CommonProxy {
private Set<EntityPlayerMP> players = new HashSet<>();
private Map<EntityPlayerMP, Set<BoundingBox>> playerBoundingBoxesCache = new HashMap<>();
- private Map<Integer, BoundingBoxVillage> villageCache = new HashMap<>();
+ private Map<DimensionType, VillageProcessor> villageProcessors = new HashMap<>();
private Map<DimensionType, ChunkProcessor> chunkProcessors = new HashMap<>();
private WorldData worldData = null;
private final Map<DimensionType, BoundingBoxCache> dimensionCache = new ConcurrentHashMap<>();
EventBus.subscribe(PlayerLoggedIn.class, e -> playerLoggedIn(e.getPlayer()));
EventBus.subscribe(PlayerLoggedOut.class, e -> playerLoggedOut(e.getPlayer()));
EventBus.subscribe(PlayerSubscribed.class, e -> sendBoundingBoxes(e.getPlayer()));
- EventBus.subscribe(Tick.class, e -> tick());
- if (ConfigManager.drawVillages.get()) {
- EventBus.subscribe(VillageUpdated.class, e -> villageUpdated(e.getDimensionType(), e.getVillage()));
- }
+ EventBus.subscribe(ServerWorldTick.class, e -> serverWorldTick(e.getWorld()));
+ EventBus.subscribe(ServerTick.class, e -> serverTick());
+ EventBus.subscribe(VillageRemoved.class, e -> sendRemoveBoundingBox(e.getDimensionType(), e.getVillage()));
}
protected void setWorldData(long seed, int spawnX, int spawnZ) {
}
Logger.info("create world dimension: %s, %s (seed: %d)", dimensionType, world.getClass().toString(), world.getSeed());
chunkProcessors.put(dimensionType, chunkProcessor);
+ villageProcessors.put(dimensionType, new VillageProcessor(dimensionType, boundingBoxCache));
}
}
sendRemoveBoundingBox(dimensionType, boundingBox);
}
- private void tick() {
+ private void serverTick() {
for (EntityPlayerMP player : players) {
DimensionType dimensionType = DimensionType.getById(player.dimension);
sendToPlayer(player, getCache(dimensionType));
}
}
- private void villageUpdated(DimensionType dimensionType, Village village) {
- BoundingBoxCache cache = getCache(dimensionType);
- if (cache == null) return;
+ private void serverWorldTick(WorldServer world) {
+ DimensionType dimensionType = world.dimension.getType();
+ VillageProcessor villageProcessor = villageProcessors.get(dimensionType);
+ if(villageProcessor == null) return;
- int villageId = village.hashCode();
- BoundingBoxVillage oldVillage = villageCache.get(villageId);
- if (oldVillage != null && !oldVillage.matches(village)) {
- cache.removeBoundingBox(oldVillage);
- sendRemoveBoundingBox(dimensionType, oldVillage);
- oldVillage = null;
- }
- if (village.isAnnihilated()) {
- villageCache.remove(villageId);
- } else {
- BoundingBoxVillage newVillage = oldVillage == null ? BoundingBoxVillage.from(village) : oldVillage;
- cache.addBoundingBox(newVillage);
- villageCache.put(villageId, newVillage);
- }
+ villageProcessor.process(world.getVillageCollection());
}
protected BoundingBoxCache getCache(DimensionType dimensionType) {
}
protected void clearCaches() {
- villageCache.clear();
+ for(VillageProcessor villageProcessor : villageProcessors.values()) {
+ villageProcessor.clear();
+ }
+ villageProcessors.clear();
for (BoundingBoxCache cache : dimensionCache.values()) {
- cache.close();
+ cache.clear();
}
dimensionCache.clear();
}
--- /dev/null
+package com.irtimaled.bbor.common;
+
+import com.irtimaled.bbor.common.events.VillageRemoved;
+import com.irtimaled.bbor.common.models.BoundingBoxVillage;
+import net.minecraft.village.Village;
+import net.minecraft.village.VillageCollection;
+import net.minecraft.world.dimension.DimensionType;
+
+import java.util.HashMap;
+import java.util.Map;
+
+class VillageProcessor {
+ private final DimensionType dimensionType;
+ private final BoundingBoxCache boundingBoxCache;
+
+ private Map<Integer, BoundingBoxVillage> villageCache = new HashMap<>();
+
+ VillageProcessor(DimensionType dimensionType, BoundingBoxCache boundingBoxCache) {
+
+ this.dimensionType = dimensionType;
+ this.boundingBoxCache = boundingBoxCache;
+ }
+
+ void process(VillageCollection villageCollection) {
+ Map<Integer, BoundingBoxVillage> oldVillages = new HashMap<>(villageCache);
+ Map<Integer, BoundingBoxVillage> newVillages = new HashMap<>();
+ for (Village village : villageCollection.getVillageList()) {
+ int villageId = village.hashCode();
+ BoundingBoxVillage newVillage = oldVillages.get(villageId);
+ if (newVillage != null && newVillage.matches(village)) {
+ oldVillages.remove(villageId);
+ } else {
+ newVillage = BoundingBoxVillage.from(village);
+ boundingBoxCache.addBoundingBox(newVillage);
+ }
+ newVillages.put(villageId, newVillage);
+ }
+ for (BoundingBoxVillage village : oldVillages.values()) {
+ boundingBoxCache.removeBoundingBox(village);
+ EventBus.publish(new VillageRemoved(dimensionType, village));
+ }
+ villageCache = newVillages;
+ }
+
+ void clear() {
+ villageCache.clear();
+ }
+}
\ No newline at end of file
--- /dev/null
+package com.irtimaled.bbor.common.events;
+
+public class ServerTick {
+}
--- /dev/null
+package com.irtimaled.bbor.common.events;
+
+import net.minecraft.world.WorldServer;
+
+public class ServerWorldTick {
+ private WorldServer world;
+
+ public ServerWorldTick(WorldServer world) {
+ this.world = world;
+ }
+
+ public WorldServer getWorld() {
+ return world;
+ }
+}
+++ /dev/null
-package com.irtimaled.bbor.common.events;
-
-public class Tick {
-}
--- /dev/null
+package com.irtimaled.bbor.common.events;
+
+import com.irtimaled.bbor.common.models.BoundingBoxVillage;
+import net.minecraft.world.dimension.DimensionType;
+
+public class VillageRemoved {
+ private final DimensionType dimensionType;
+ private final BoundingBoxVillage village;
+
+ public VillageRemoved(DimensionType dimensionType, BoundingBoxVillage village) {
+
+ this.dimensionType = dimensionType;
+ this.village = village;
+ }
+
+ public DimensionType getDimensionType() {
+ return dimensionType;
+ }
+
+ public BoundingBoxVillage getVillage() {
+ return village;
+ }
+}
+++ /dev/null
-package com.irtimaled.bbor.common.events;
-
-import net.minecraft.village.Village;
-import net.minecraft.world.dimension.DimensionType;
-
-public class VillageUpdated {
- private final DimensionType dimensionType;
- private final Village village;
-
- public VillageUpdated(DimensionType dimensionType, Village village) {
- this.dimensionType = dimensionType;
- this.village = village;
- }
-
- public DimensionType getDimensionType() {
- return dimensionType;
- }
-
- public Village getVillage() {
- return village;
- }
-}
}
public static BoundingBoxVillage from(BlockPos center, Integer radius, int villageId, int population, Set<BlockPos> doors) {
- Boolean spawnsIronGolems = shouldSpawnIronGolems(population, doors.size());
+ boolean spawnsIronGolems = shouldSpawnIronGolems(population, doors.size());
Color color = VillageColorCache.getColor(villageId);
return from(center, radius, color, spawnsIronGolems, doors);
}
private static Set<BlockPos> getDoorsFromVillage(Village village) {
Set<BlockPos> doors = new HashSet<>();
List<VillageDoorInfo> doorInfoList = village.getVillageDoorInfoList();
- for (int i = 0; i < doorInfoList.size(); i++) {
- VillageDoorInfo doorInfo = doorInfoList.get(i);
+ for (VillageDoorInfo doorInfo : doorInfoList) {
doors.add(doorInfo.getDoorBlockPos());
}
return doors;
package com.irtimaled.bbor.mixin.server;
import com.irtimaled.bbor.common.EventBus;
-import com.irtimaled.bbor.common.events.Tick;
+import com.irtimaled.bbor.common.events.ServerTick;
import com.irtimaled.bbor.common.events.WorldLoaded;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.World;
@Inject(method = "tick", at = @At("RETURN"))
private void tick(CallbackInfo ci) {
- EventBus.publish(new Tick());
+ EventBus.publish(new ServerTick());
}
}
+++ /dev/null
-package com.irtimaled.bbor.mixin.village;
-
-import com.irtimaled.bbor.common.EventBus;
-import com.irtimaled.bbor.common.events.VillageUpdated;
-import net.minecraft.village.Village;
-import net.minecraft.world.World;
-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.Redirect;
-import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
-
-@Mixin(Village.class)
-public abstract class MixinVillage {
- @Shadow
- protected abstract void updateVillagerCount();
-
- @Shadow
- private int villagerCount;
-
- @Shadow private World world;
-
- @Inject(method = "updateVillageRadiusAndCenter", at = @At("HEAD"))
- private void updateVillageRadiusAndCenter(CallbackInfo ci) {
- Village village = (Village) (Object) this;
- publishVillageUpdated(village);
- }
-
- private void publishVillageUpdated(Village village) {
- EventBus.publish(new VillageUpdated(world.dimension.getType(), village));
- }
-
- @Redirect(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/village/Village;updateVillagerCount()V"))
- private void tick(Village village) {
- int population = this.villagerCount;
- this.updateVillagerCount();
- if (this.villagerCount != population)
- publishVillageUpdated(village);
- }
-}
--- /dev/null
+package com.irtimaled.bbor.mixin.world;
+
+import com.irtimaled.bbor.common.EventBus;
+import com.irtimaled.bbor.common.events.ServerWorldTick;
+import net.minecraft.world.WorldServer;
+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(WorldServer.class)
+public class MixinWorldServer {
+ @Inject(method = "tick", at=@At(value = "INVOKE", target = "Lnet/minecraft/village/VillageCollection;tick()V", shift = At.Shift.AFTER))
+ private void afterVillageTick(CallbackInfo ci) {
+ EventBus.publish(new ServerWorldTick((WorldServer)(Object)this));
+ }
+
+}
"refmap": "mixins.bbor.refmap.json",
"mixins": [
"world.chunk.MixinChunk",
+ "world.MixinWorldServer",
"network.play.client.MixinCPacketCustomPayload",
- "village.MixinVillage",
"server.management.MixinPlayerList",
"server.management.MixinPlayerInteractionManager",
"server.MixinMinecraftServer"