package com.irtimaled.bbor.client;
-import com.irtimaled.bbor.client.events.ConnectedToRemoteServer;
-import com.irtimaled.bbor.client.events.DisconnectedFromRemoteServer;
-import com.irtimaled.bbor.client.events.KeyPressed;
-import com.irtimaled.bbor.client.events.RenderEvent;
-import com.irtimaled.bbor.common.CommonProxy;
-import com.irtimaled.bbor.common.EventBus;
-import com.irtimaled.bbor.common.VillageColorCache;
-import com.irtimaled.bbor.common.VillageProcessor;
+import com.irtimaled.bbor.client.events.*;
+import com.irtimaled.bbor.common.*;
+import com.irtimaled.bbor.common.events.Tick;
+import com.irtimaled.bbor.common.models.BoundingBox;
import com.irtimaled.bbor.config.ConfigManager;
import net.minecraft.client.Minecraft;
import net.minecraft.client.settings.KeyBinding;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
+import java.util.Set;
public class ClientProxy extends CommonProxy {
public static final String KeyCategory = "Bounding Box Outline Reloaded";
EventBus.subscribe(KeyPressed.class, e -> keyPressed());
EventBus.subscribe(ConnectedToRemoteServer.class, e -> connectedToServer(e.getNetworkManager()));
EventBus.subscribe(DisconnectedFromRemoteServer.class, e -> disconnectedFromServer());
+ EventBus.subscribe(InitializeClientReceived.class, e -> dimensionCache.setWorldData(e.getSeed(), e.getSpawnX(), e.getSpawnZ()));
+ EventBus.subscribe(AddBoundingBoxReceived.class, e -> addBoundingBox(e.getDimensionType(), e.getKey(), e.getBoundingBoxes()));
+ EventBus.subscribe(RemoveBoundingBoxReceived.class, e -> removeBoundingBox(e.getDimensionType(), e.getKey()));
+ EventBus.subscribe(Tick.class, e -> tick());
}
private void render(float partialTicks) {
PlayerData.setPlayerPosition(partialTicks, entityPlayer);
if (this.active) {
- tick();
renderer.render(DimensionType.getById(entityPlayer.dimension), outerBoxOnly);
}
}
+ @Override
+ protected void tick() {
+ if (this.active || hasRemoteUsers()) {
+ super.tick();
+ }
+ }
+
private void keyPressed() {
if (ActiveHotKey.isPressed()) {
active = !active;
VillageColorCache.clear();
dimensionCache.clear();
}
+
+ private void addBoundingBox(DimensionType dimensionType, BoundingBox key, Set<BoundingBox> boundingBoxes) {
+ BoundingBoxCache cache = dimensionCache.get(dimensionType);
+ if (cache == null) {
+ dimensionCache.put(dimensionType, cache = new BoundingBoxCache());
+ }
+
+ cache.addBoundingBoxes(key, boundingBoxes);
+ }
}
\ No newline at end of file
--- /dev/null
+package com.irtimaled.bbor.client.events;
+
+import com.irtimaled.bbor.common.models.BoundingBox;
+import net.minecraft.world.dimension.DimensionType;
+
+import java.util.Set;
+
+public class AddBoundingBoxReceived {
+ private final DimensionType dimensionType;
+ private final BoundingBox key;
+ private final Set<BoundingBox> boundingBoxes;
+
+ public AddBoundingBoxReceived(DimensionType dimensionType, BoundingBox key, Set<BoundingBox> boundingBoxes) {
+ this.dimensionType = dimensionType;
+ this.key = key;
+ this.boundingBoxes = boundingBoxes;
+ }
+
+ public DimensionType getDimensionType() {
+ return dimensionType;
+ }
+
+ public BoundingBox getKey() {
+ return key;
+ }
+
+ public Set<BoundingBox> getBoundingBoxes() {
+ return boundingBoxes;
+ }
+}
--- /dev/null
+package com.irtimaled.bbor.client.events;
+
+public class InitializeClientReceived {
+ private final long seed;
+ private final int spawnX;
+ private final int spawnZ;
+
+ public InitializeClientReceived(long seed, int spawnX, int spawnZ) {
+ this.seed = seed;
+ this.spawnX = spawnX;
+ this.spawnZ = spawnZ;
+ }
+
+ public long getSeed() {
+ return seed;
+ }
+
+ public int getSpawnX() {
+ return spawnX;
+ }
+
+ public int getSpawnZ() {
+ return spawnZ;
+ }
+}
--- /dev/null
+package com.irtimaled.bbor.client.events;
+
+import com.irtimaled.bbor.common.models.BoundingBox;
+import net.minecraft.world.dimension.DimensionType;
+
+public class RemoveBoundingBoxReceived {
+ private final DimensionType dimensionType;
+ private final BoundingBox key;
+
+ public RemoveBoundingBoxReceived(DimensionType dimensionType, BoundingBox key) {
+ this.dimensionType = dimensionType;
+ this.key = key;
+ }
+
+ public DimensionType getDimensionType() {
+ return dimensionType;
+ }
+
+ public BoundingBox getKey() {
+ return key;
+ }
+}
package com.irtimaled.bbor.common;
import com.irtimaled.bbor.Logger;
-import com.irtimaled.bbor.common.events.ChunkLoaded;
-import com.irtimaled.bbor.common.events.MobSpawnerBroken;
-import com.irtimaled.bbor.common.events.WorldLoaded;
+import com.irtimaled.bbor.common.events.*;
+import com.irtimaled.bbor.common.messages.AddBoundingBox;
+import com.irtimaled.bbor.common.messages.InitializeClient;
+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.config.ConfigManager;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.network.play.server.SPacketCustomPayload;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.dimension.DimensionType;
import net.minecraft.world.gen.ChunkProviderServer;
+import java.util.HashMap;
import java.util.HashSet;
+import java.util.Map;
import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
public class CommonProxy {
+ private Map<EntityPlayerMP, DimensionType> playerDimensions = new ConcurrentHashMap<>();
+ private Map<EntityPlayerMP, Set<BoundingBox>> playerBoundingBoxesCache = new HashMap<>();
+
protected DimensionCache dimensionCache;
protected Set<VillageProcessor> villageProcessors = new HashSet<>();
EventBus.subscribe(WorldLoaded.class, e -> worldLoaded(e.getWorld()));
EventBus.subscribe(ChunkLoaded.class, e -> chunkLoaded(e.getChunk()));
EventBus.subscribe(MobSpawnerBroken.class, e -> mobSpawnerBroken(e.getDimensionType(), e.getPos()));
+ EventBus.subscribe(PlayerChangedDimension.class, e -> playerChangedDimension(e.getPlayer()));
+ EventBus.subscribe(PlayerLoggedIn.class, e -> playerLoggedIn(e.getPlayer()));
+ EventBus.subscribe(PlayerLoggedOut.class, e -> playerLoggedOut(e.getPlayer()));
+ EventBus.subscribe(VillageRemoved.class, e -> sendRemoveBoundingBox(e.getDimensionType(), e.getBoundingBox()));
+ EventBus.subscribe(PlayerSubscribed.class, e -> sendBoundingBoxes(e.getPlayer()));
+ EventBus.subscribe(Tick.class, e -> tick());
+ }
+
+ protected boolean hasRemoteUsers() {
+ return playerDimensions.size() > 0;
}
private void worldLoaded(World world) {
DimensionProcessor boundingBoxCache = new DimensionProcessor(dimensionType);
dimensionCache.put(dimensionType, boundingBoxCache);
if (ConfigManager.drawVillages.getBoolean()) {
- villageProcessors.add(new VillageProcessor(world, boundingBoxCache));
+ villageProcessors.add(new VillageProcessor(world, dimensionType, boundingBoxCache));
}
}
}
}
}
- protected void tick() {
- villageProcessors.forEach(VillageProcessor::process);
+ private void playerChangedDimension(EntityPlayerMP player) {
+ if (playerDimensions.containsKey(player)) {
+ sendBoundingBoxes(player);
+ }
}
- private void mobSpawnerBroken(DimensionType dimensionType, BlockPos pos) {
- BoundingBox boundingBox = BoundingBoxMobSpawner.from(pos);
+ private void playerLoggedIn(EntityPlayerMP player) {
+ player.connection.sendPacket(InitializeClient.getPayload(dimensionCache.getWorldData()));
+ }
+
+ private void playerLoggedOut(EntityPlayerMP player) {
+ playerDimensions.remove(player);
+ playerBoundingBoxesCache.remove(player);
+ }
+
+ private void sendRemoveBoundingBox(DimensionType dimensionType, BoundingBox boundingBox) {
+ SPacketCustomPayload payload = RemoveBoundingBox.getPayload(dimensionType, boundingBox);
+ for (EntityPlayerMP player : playerDimensions.keySet()) {
+ if (DimensionType.getById(player.dimension) == dimensionType) {
+ Logger.info("remove 1 entry from %s (%s)", player.getScoreboardName(), dimensionType);
+ player.connection.sendPacket(payload);
+
+ if (playerBoundingBoxesCache.containsKey(player)) {
+ playerBoundingBoxesCache.get(player).remove(boundingBox);
+ }
+ }
+ }
+ }
+
+ private void sendBoundingBoxes(EntityPlayerMP player) {
+ DimensionType dimensionType = DimensionType.getById(player.dimension);
+ playerDimensions.put(player, dimensionType);
+ sendToPlayer(player, dimensionCache.getBoundingBoxes(dimensionType));
+ }
+
+ private void sendToPlayer(EntityPlayerMP player, BoundingBoxCache boundingBoxCache) {
+ if (boundingBoxCache == null)
+ return;
+ Map<BoundingBox, Set<BoundingBox>> cacheSubset = getBoundingBoxMap(player, boundingBoxCache.getBoundingBoxes());
+
+ DimensionType dimensionType = DimensionType.getById(player.dimension);
+ if (cacheSubset.keySet().size() > 0) {
+ Logger.info("send %d entries to %s (%s)", cacheSubset.keySet().size(), player.getScoreboardName(), dimensionType);
+ }
+
+ for (BoundingBox key : cacheSubset.keySet()) {
+ Set<BoundingBox> boundingBoxes = cacheSubset.get(key);
+ player.connection.sendPacket(AddBoundingBox.getPayload(dimensionType, key, boundingBoxes));
+
+ if (!playerBoundingBoxesCache.containsKey(player)) {
+ playerBoundingBoxesCache.put(player, new HashSet<>());
+ }
+ playerBoundingBoxesCache.get(player).add(key);
+ }
+ }
+
+ private Map<BoundingBox, Set<BoundingBox>> getBoundingBoxMap(EntityPlayerMP player, Map<BoundingBox, Set<BoundingBox>> boundingBoxMap) {
+ Map<BoundingBox, Set<BoundingBox>> cacheSubset = new HashMap<>();
+ for (BoundingBox key : boundingBoxMap.keySet()) {
+ if (!playerBoundingBoxesCache.containsKey(player) || !playerBoundingBoxesCache.get(player).contains(key)) {
+ cacheSubset.put(key, boundingBoxMap.get(key));
+ }
+ }
+ return cacheSubset;
+ }
+
+ protected void removeBoundingBox(DimensionType dimensionType, BoundingBox key) {
BoundingBoxCache cache = dimensionCache.getBoundingBoxes(dimensionType);
if (cache != null) {
- cache.removeBoundingBox(boundingBox);
+ cache.removeBoundingBox(key);
+ }
+ }
+
+ private void mobSpawnerBroken(DimensionType dimensionType, BlockPos pos) {
+ BoundingBox boundingBox = BoundingBoxMobSpawner.from(pos);
+ removeBoundingBox(dimensionType, boundingBox);
+ sendRemoveBoundingBox(dimensionType, boundingBox);
+ }
+
+ protected void tick() {
+ villageProcessors.forEach(VillageProcessor::process);
+ for (EntityPlayerMP player : playerDimensions.keySet()) {
+ DimensionType dimensionType = playerDimensions.get(player);
+ sendToPlayer(player, dimensionCache.getBoundingBoxes(dimensionType));
}
}
}
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.World;
+import net.minecraft.world.dimension.DimensionType;
import java.util.HashMap;
import java.util.List;
public class VillageProcessor {
private World world;
+ private DimensionType dimensionType;
private BoundingBoxCache boundingBoxCache;
private Map<Integer, BoundingBoxVillage> villageCache = new HashMap<>();
private boolean closed = false;
- VillageProcessor(World world, BoundingBoxCache boundingBoxCache) {
+ VillageProcessor(World world, DimensionType dimensionType, BoundingBoxCache boundingBoxCache) {
this.world = world;
+ this.dimensionType = dimensionType;
this.boundingBoxCache = boundingBoxCache;
}
}
for (BoundingBoxVillage village : oldVillages.values()) {
boundingBoxCache.removeBoundingBox(village);
+ EventBus.publish(new VillageRemoved(dimensionType, village));
}
for (BoundingBoxVillage village : newVillages.values()) {
boundingBoxCache.addBoundingBox(village);
--- /dev/null
+package com.irtimaled.bbor.common.events;
+
+import net.minecraft.entity.player.EntityPlayerMP;
+
+public class PlayerChangedDimension {
+ private final EntityPlayerMP player;
+
+ public PlayerChangedDimension(EntityPlayerMP player) {
+ this.player = player;
+ }
+
+ public EntityPlayerMP getPlayer() {
+ return player;
+ }
+}
--- /dev/null
+package com.irtimaled.bbor.common.events;
+
+import net.minecraft.entity.player.EntityPlayerMP;
+
+public class PlayerLoggedIn {
+ private final EntityPlayerMP player;
+
+ public PlayerLoggedIn(EntityPlayerMP player) {
+ this.player = player;
+ }
+
+ public EntityPlayerMP getPlayer() {
+ return player;
+ }
+}
--- /dev/null
+package com.irtimaled.bbor.common.events;
+
+import net.minecraft.entity.player.EntityPlayerMP;
+
+public class PlayerLoggedOut {
+ private final EntityPlayerMP player;
+
+ public PlayerLoggedOut(EntityPlayerMP player) {
+ this.player = player;
+ }
+
+ public EntityPlayerMP getPlayer() {
+ return player;
+ }
+}
--- /dev/null
+package com.irtimaled.bbor.common.events;
+
+import net.minecraft.entity.player.EntityPlayerMP;
+
+public class PlayerSubscribed {
+ private final EntityPlayerMP player;
+
+ public PlayerSubscribed(EntityPlayerMP player) {
+ this.player = player;
+ }
+
+ public EntityPlayerMP getPlayer() {
+ return player;
+ }
+}
--- /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.BoundingBox;
+import net.minecraft.world.dimension.DimensionType;
+
+public class VillageRemoved {
+ private final DimensionType dimensionType;
+ private final BoundingBox boundingBox;
+
+ public VillageRemoved(DimensionType dimensionType, BoundingBox boundingBox) {
+ this.dimensionType = dimensionType;
+ this.boundingBox = boundingBox;
+ }
+
+ public DimensionType getDimensionType() {
+ return dimensionType;
+ }
+
+ public BoundingBox getBoundingBox() {
+ return boundingBox;
+ }
+}
--- /dev/null
+package com.irtimaled.bbor.common.messages;
+
+import com.irtimaled.bbor.client.events.AddBoundingBoxReceived;
+import com.irtimaled.bbor.common.models.BoundingBox;
+import io.netty.buffer.Unpooled;
+import net.minecraft.network.PacketBuffer;
+import net.minecraft.network.play.server.SPacketCustomPayload;
+import net.minecraft.util.ResourceLocation;
+import net.minecraft.world.dimension.DimensionType;
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class AddBoundingBox {
+ public static final ResourceLocation NAME = new ResourceLocation("bbor:add_bounding_box");
+
+ public static SPacketCustomPayload getPayload(DimensionType dimensionType, BoundingBox key, Set<BoundingBox> boundingBoxes) {
+ PacketBuffer buf = new PacketBuffer(Unpooled.buffer());
+ buf.writeVarInt(dimensionType.getId());
+ BoundingBoxSerializer.serialize(key, buf);
+ if (boundingBoxes != null && boundingBoxes.size() > 1) {
+ for (BoundingBox boundingBox : boundingBoxes) {
+ BoundingBoxSerializer.serialize(boundingBox, buf);
+ }
+ }
+ return new SPacketCustomPayload(NAME, buf);
+ }
+
+ public static AddBoundingBoxReceived getEvent(PacketBuffer buf) {
+ DimensionType dimensionType = DimensionType.getById(buf.readVarInt());
+ BoundingBox key = BoundingBoxDeserializer.deserialize(buf);
+ Set<BoundingBox> boundingBoxes = new HashSet<>();
+ while (buf.isReadable()) {
+ BoundingBox boundingBox = BoundingBoxDeserializer.deserialize(buf);
+ boundingBoxes.add(boundingBox);
+ }
+ if (boundingBoxes.size() == 0)
+ boundingBoxes.add(key);
+ return new AddBoundingBoxReceived(dimensionType, key, boundingBoxes);
+ }
+}
--- /dev/null
+package com.irtimaled.bbor.common.messages;
+
+import com.irtimaled.bbor.common.models.BoundingBox;
+import com.irtimaled.bbor.common.models.BoundingBoxMobSpawner;
+import com.irtimaled.bbor.common.models.BoundingBoxStructure;
+import com.irtimaled.bbor.common.models.BoundingBoxVillage;
+import net.minecraft.network.PacketBuffer;
+import net.minecraft.util.math.BlockPos;
+
+import java.awt.*;
+import java.util.HashSet;
+import java.util.Set;
+
+public class BoundingBoxDeserializer {
+ static BoundingBox deserialize(PacketBuffer buf) {
+ char type = buf.readChar();
+ switch (type) {
+ case 'V':
+ return deserializeVillage(buf);
+ case 'S':
+ return deserializeStructure(buf);
+ case 'M':
+ return deserializeMobSpawner(buf);
+ }
+ return null;
+ }
+
+ private static BoundingBox deserializeStructure(PacketBuffer buf) {
+ BlockPos minBlockPos = deserializeBlockPos(buf);
+ BlockPos maxBlockPos = deserializeBlockPos(buf);
+ Color color = new Color(buf.readVarInt());
+ return BoundingBoxStructure.from(minBlockPos, maxBlockPos, color);
+ }
+
+ private static BoundingBox deserializeVillage(PacketBuffer buf) {
+ BlockPos center = deserializeBlockPos(buf);
+ int radius = buf.readVarInt();
+ boolean spawnsIronGolems = buf.readBoolean();
+ Color color = new Color(buf.readVarInt());
+ Set<BlockPos> doors = new HashSet<>();
+ while (buf.isReadable()) {
+ BlockPos door = deserializeBlockPos(buf);
+ doors.add(door);
+ }
+ return BoundingBoxVillage.from(center, radius, color, spawnsIronGolems, doors);
+ }
+
+ private static BoundingBox deserializeMobSpawner(PacketBuffer buf) {
+ BlockPos center = deserializeBlockPos(buf);
+ return BoundingBoxMobSpawner.from(center);
+ }
+
+ private static BlockPos deserializeBlockPos(PacketBuffer buf) {
+ int x = buf.readVarInt();
+ int y = buf.readVarInt();
+ int z = buf.readVarInt();
+ return new BlockPos(x, y, z);
+ }
+}
--- /dev/null
+package com.irtimaled.bbor.common.messages;
+
+import com.irtimaled.bbor.common.models.BoundingBox;
+import com.irtimaled.bbor.common.models.BoundingBoxMobSpawner;
+import com.irtimaled.bbor.common.models.BoundingBoxStructure;
+import com.irtimaled.bbor.common.models.BoundingBoxVillage;
+import net.minecraft.network.PacketBuffer;
+import net.minecraft.util.math.BlockPos;
+
+import java.awt.*;
+
+public class BoundingBoxSerializer {
+ static void serialize(BoundingBox boundingBox, PacketBuffer buf) {
+ if (boundingBox instanceof BoundingBoxVillage) {
+ serializeVillage((BoundingBoxVillage) boundingBox, buf);
+ }
+ if (boundingBox instanceof BoundingBoxStructure) {
+ serializeStructure((BoundingBoxStructure) boundingBox, buf);
+ }
+ if (boundingBox instanceof BoundingBoxMobSpawner) {
+ serializeMobSpawner((BoundingBoxMobSpawner) boundingBox, buf);
+ }
+ }
+
+ private static void serializeVillage(BoundingBoxVillage boundingBox, PacketBuffer buf) {
+ buf.writeChar('V');
+ serializeBlockPos(boundingBox.getCenter(), buf);
+ buf.writeVarInt(boundingBox.getRadius());
+ buf.writeBoolean(boundingBox.getSpawnsIronGolems());
+ serializeColor(boundingBox.getColor(), buf);
+ for (BlockPos door : boundingBox.getDoors()) {
+ serializeBlockPos(door, buf);
+ }
+ }
+
+ private static void serializeStructure(BoundingBoxStructure boundingBox, PacketBuffer buf) {
+ buf.writeChar('S');
+ serializeCuboid(boundingBox, buf);
+ serializeColor(boundingBox.getColor(), buf);
+ }
+
+ private static void serializeMobSpawner(BoundingBoxMobSpawner boundingBox, PacketBuffer buf) {
+ buf.writeChar('M');
+ serializeBlockPos(boundingBox.getCenter(), buf);
+ }
+
+ private static void serializeColor(Color color, PacketBuffer buf) {
+ buf.writeVarInt(color.getRGB());
+ }
+
+ private static void serializeCuboid(BoundingBox boundingBox, PacketBuffer buf) {
+ serializeBlockPos(boundingBox.getMinBlockPos(), buf);
+ serializeBlockPos(boundingBox.getMaxBlockPos(), buf);
+ }
+
+ private static void serializeBlockPos(BlockPos blockPos, PacketBuffer buf) {
+ buf.writeVarInt(blockPos.getX());
+ buf.writeVarInt(blockPos.getY());
+ buf.writeVarInt(blockPos.getZ());
+ }
+}
--- /dev/null
+package com.irtimaled.bbor.common.messages;
+
+import com.irtimaled.bbor.client.events.InitializeClientReceived;
+import com.irtimaled.bbor.common.models.WorldData;
+import io.netty.buffer.Unpooled;
+import net.minecraft.network.PacketBuffer;
+import net.minecraft.network.play.server.SPacketCustomPayload;
+import net.minecraft.util.ResourceLocation;
+
+public class InitializeClient {
+ public static final ResourceLocation NAME = new ResourceLocation("bbor:initialize");
+
+ public static SPacketCustomPayload getPayload(WorldData worldData) {
+ PacketBuffer buf = new PacketBuffer(Unpooled.buffer());
+ buf.writeLong(worldData.getSeed());
+ buf.writeInt(worldData.getSpawnX());
+ buf.writeInt(worldData.getSpawnZ());
+
+ return new SPacketCustomPayload(NAME, buf);
+ }
+
+ public static InitializeClientReceived getEvent(PacketBuffer buf) {
+ long seed = buf.readLong();
+ int spawnX = buf.readInt();
+ int spawnZ = buf.readInt();
+ return new InitializeClientReceived(seed, spawnX, spawnZ);
+ }
+}
--- /dev/null
+package com.irtimaled.bbor.common.messages;
+
+import com.irtimaled.bbor.client.events.RemoveBoundingBoxReceived;
+import com.irtimaled.bbor.common.models.BoundingBox;
+import io.netty.buffer.Unpooled;
+import net.minecraft.network.PacketBuffer;
+import net.minecraft.network.play.server.SPacketCustomPayload;
+import net.minecraft.util.ResourceLocation;
+import net.minecraft.world.dimension.DimensionType;
+
+public class RemoveBoundingBox {
+ public static final ResourceLocation NAME = new ResourceLocation("bbor:remove_bounding_box");
+
+ public static SPacketCustomPayload getPayload(DimensionType dimensionType, BoundingBox key) {
+ PacketBuffer buf = new PacketBuffer(Unpooled.buffer());
+ buf.writeVarInt(dimensionType.getId());
+ BoundingBoxSerializer.serialize(key, buf);
+
+ return new SPacketCustomPayload(NAME, buf);
+ }
+
+ public static RemoveBoundingBoxReceived getEvent(PacketBuffer buf) {
+ DimensionType dimensionType = DimensionType.getById(buf.readVarInt());
+ BoundingBox key = BoundingBoxDeserializer.deserialize(buf);
+ return new RemoveBoundingBoxReceived(dimensionType, key);
+ }
+}
--- /dev/null
+package com.irtimaled.bbor.common.messages;
+
+import io.netty.buffer.Unpooled;
+import net.minecraft.network.PacketBuffer;
+import net.minecraft.network.play.client.CPacketCustomPayload;
+import net.minecraft.util.ResourceLocation;
+
+public class SubscribeToServer {
+ public static final ResourceLocation NAME = new ResourceLocation("bbor:subscribe");
+
+ public static CPacketCustomPayload getPayload() {
+ return new CPacketCustomPayload(NAME, new PacketBuffer(Unpooled.buffer()));
+ }
+}
--- /dev/null
+package com.irtimaled.bbor.mixin.entity.player;
+
+import com.irtimaled.bbor.common.EventBus;
+import com.irtimaled.bbor.common.events.PlayerChangedDimension;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.player.EntityPlayerMP;
+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.CallbackInfoReturnable;
+
+@Mixin(EntityPlayerMP.class)
+public class MixinEntityPlayerMP {
+ @Inject(method = "changeDimension", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/management/PlayerList;changePlayerDimension(Lnet/minecraft/entity/player/EntityPlayerMP;I)V"))
+ private void changeDimension(int dimensionId, CallbackInfoReturnable<Entity> cir) {
+ EventBus.publish(new PlayerChangedDimension((EntityPlayerMP) (Object) this));
+ }
+}
--- /dev/null
+package com.irtimaled.bbor.mixin.network.play.client;
+
+import com.irtimaled.bbor.common.EventBus;
+import com.irtimaled.bbor.common.events.PlayerSubscribed;
+import com.irtimaled.bbor.common.messages.SubscribeToServer;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.network.NetHandlerPlayServer;
+import net.minecraft.network.play.INetHandlerPlayServer;
+import net.minecraft.network.play.client.CPacketCustomPayload;
+import net.minecraft.util.ResourceLocation;
+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.Redirect;
+
+@Mixin(CPacketCustomPayload.class)
+public class MixinCPacketCustomPayload {
+ @Shadow
+ private ResourceLocation channel;
+
+ @Redirect(method = "processPacket", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/play/INetHandlerPlayServer;processCustomPayload(Lnet/minecraft/network/play/client/CPacketCustomPayload;)V"))
+ private void processPacket(INetHandlerPlayServer netHandlerPlayServer, CPacketCustomPayload packet) {
+ if (this.channel.equals(SubscribeToServer.NAME)) {
+ EntityPlayerMP player = ((NetHandlerPlayServer) netHandlerPlayServer).player;
+ EventBus.publish(new PlayerSubscribed(player));
+ } else {
+ netHandlerPlayServer.processCustomPayload(packet);
+ }
+ }
+}
--- /dev/null
+package com.irtimaled.bbor.mixin.network.play.server;
+
+import com.irtimaled.bbor.common.EventBus;
+import com.irtimaled.bbor.common.messages.AddBoundingBox;
+import com.irtimaled.bbor.common.messages.InitializeClient;
+import com.irtimaled.bbor.common.messages.RemoveBoundingBox;
+import com.irtimaled.bbor.common.messages.SubscribeToServer;
+import net.minecraft.client.network.NetHandlerPlayClient;
+import net.minecraft.network.PacketBuffer;
+import net.minecraft.network.play.INetHandlerPlayClient;
+import net.minecraft.network.play.server.SPacketCustomPayload;
+import net.minecraft.util.ResourceLocation;
+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.Redirect;
+
+@Mixin(SPacketCustomPayload.class)
+public abstract class MixinSPacketCustomPayload {
+ @Shadow
+ private ResourceLocation channel;
+
+ @Redirect(method = "processPacket", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/play/INetHandlerPlayClient;handleCustomPayload(Lnet/minecraft/network/play/server/SPacketCustomPayload;)V"))
+ private void processPacket(INetHandlerPlayClient netHandlerPlayClient, SPacketCustomPayload packet) {
+ PacketBuffer data = null;
+ try {
+ data = packet.getBufferData();
+ if (InitializeClient.NAME.equals(channel)) {
+ EventBus.publish(InitializeClient.getEvent(data));
+ ((NetHandlerPlayClient) netHandlerPlayClient).sendPacket(SubscribeToServer.getPayload());
+ } else if (AddBoundingBox.NAME.equals(channel)) {
+ EventBus.publish(AddBoundingBox.getEvent(data));
+ } else if (RemoveBoundingBox.NAME.equals(channel)) {
+ EventBus.publish(RemoveBoundingBox.getEvent(data));
+ } else {
+ netHandlerPlayClient.handleCustomPayload(packet);
+ }
+ } finally {
+ if (data != null)
+ data.release();
+ }
+ }
+}
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.WorldLoaded;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.World;
EventBus.publish(new WorldLoaded(world));
}
}
+
+ @Inject(method = "tick", at = @At("RETURN"))
+ private void tick(CallbackInfo ci) {
+ EventBus.publish(new Tick());
+ }
}
--- /dev/null
+package com.irtimaled.bbor.mixin.server.dedicated;
+
+import com.irtimaled.bbor.common.CommonProxy;
+import com.irtimaled.bbor.config.ConfigManager;
+import net.minecraft.server.dedicated.DedicatedServer;
+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.CallbackInfoReturnable;
+
+import java.io.File;
+
+@Mixin(DedicatedServer.class)
+public class MixinDedicatedServer {
+ @Inject(method = "init", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/dedicated/DedicatedServer;loadAllWorlds(Ljava/lang/String;Ljava/lang/String;JLnet/minecraft/world/WorldType;Lcom/google/gson/JsonElement;)V"))
+ private void init(CallbackInfoReturnable<Boolean> cir) {
+ File gameDir = ((DedicatedServer) (Object) this).getDataDirectory();
+ ConfigManager.loadConfig(gameDir);
+ new CommonProxy().init();
+ }
+}
\ No newline at end of file
--- /dev/null
+package com.irtimaled.bbor.mixin.server.management;
+
+import com.irtimaled.bbor.common.EventBus;
+import com.irtimaled.bbor.common.events.PlayerLoggedIn;
+import com.irtimaled.bbor.common.events.PlayerLoggedOut;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.server.management.PlayerList;
+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(PlayerList.class)
+public class MixinPlayerList {
+ @Inject(method = "playerLoggedIn", at = @At("RETURN"))
+ private void playerLoggedIn(EntityPlayerMP player, CallbackInfo ci) {
+ if (player.world.isRemote) {
+ EventBus.publish(new PlayerLoggedIn(player));
+ }
+ }
+
+ @Inject(method = "playerLoggedOut", at = @At("HEAD"))
+ private void playerLoggedOut(EntityPlayerMP player, CallbackInfo ci) {
+ if (player.world.isRemote) {
+ EventBus.publish(new PlayerLoggedOut(player));
+ }
+ }
+}
"refmap": "mixins.bbor.refmap.json",
"mixins": [
"world.chunk.MixinChunk",
+ "network.play.client.MixinCPacketCustomPayload",
+ "network.play.server.MixinSPacketCustomPayload",
+ "entity.player.MixinEntityPlayerMP",
+ "server.management.MixinPlayerList",
"server.management.MixinPlayerInteractionManager",
"server.MixinMinecraftServer"
],
"client.network.MixinNetHandlerLoginClient",
"client.settings.MixinKeyBinding",
"client.settings.MixinGameSettings"
+ ],
+ "server": [
+ "server.dedicated.MixinDedicatedServer"
]
}