Serialize and Sync Gate Expansions

Expansions are synced in a similar manner to fluid ids. A packet is sent
on login with a String<->Byte mapping for each Expansion. The Pipe uses
this lookup table construct the Gate on the client side.

Remaining Todo List:
-Add Integration Table for adding Expansions to Gates
-Add Deconstruction Table for dismantling Gates
-Adapt Clock Timer Expansion to new framework
-Add Redstone Fader Expansion (name not final)
This commit is contained in:
CovertJaguar 2013-12-21 19:11:51 -08:00
parent 88c320a56b
commit a0c2e5807c
12 changed files with 238 additions and 22 deletions

View file

@ -43,6 +43,7 @@ import buildcraft.transport.gates.GateExpansionPulsar;
import buildcraft.api.gates.GateExpansions;
import buildcraft.api.transport.PipeWire;
import buildcraft.transport.network.PacketHandlerTransport;
import buildcraft.transport.network.TransportConnectionHandler;
import buildcraft.transport.pipes.PipeFluidsCobblestone;
import buildcraft.transport.pipes.PipeFluidsEmerald;
import buildcraft.transport.pipes.PipeFluidsGold;
@ -107,7 +108,7 @@ import net.minecraftforge.common.ForgeDirection;
import net.minecraftforge.common.Property;
@Mod(version = Version.VERSION, modid = "BuildCraft|Transport", name = "Buildcraft Transport", dependencies = DefaultProps.DEPENDENCY_CORE)
@NetworkMod(channels = {DefaultProps.NET_CHANNEL_NAME}, packetHandler = PacketHandlerTransport.class)
@NetworkMod(channels = {DefaultProps.NET_CHANNEL_NAME}, packetHandler = PacketHandlerTransport.class, connectionHandler = TransportConnectionHandler.class)
public class BuildCraftTransport {
public static BlockGenericPipe genericPipeBlock;

View file

@ -8,8 +8,12 @@
*/
package buildcraft.api.gates;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
*
@ -17,12 +21,49 @@ import java.util.Map;
*/
public final class GateExpansions {
public static final Map<String, IGateExpansion> expansions = new HashMap<String, IGateExpansion>();
private static final Map<String, IGateExpansion> expansions = new HashMap<String, IGateExpansion>();
private static final BiMap<Byte, String> serverIDMap = HashBiMap.create();
private static final BiMap<Byte, String> clientIDMap = HashBiMap.create();
private static byte nextID = 0;
private GateExpansions() {
}
public static void registerExpansion(IGateExpansion expansion) {
expansions.put(expansion.getUniqueIdentifier(), expansion);
registerExpansion(expansion.getUniqueIdentifier(), expansion);
}
public static void registerExpansion(String identifier, IGateExpansion expansion) {
expansions.put(identifier, expansion);
serverIDMap.put(nextID++, identifier);
}
public static IGateExpansion getExpansion(String identifier) {
return expansions.get(identifier);
}
public static IGateExpansion getExpansionClient(int id) {
if (id < 0 || id >= 128)
return null;
return expansions.get(clientIDMap.get((byte) id));
}
public static byte getServerExpansionID(String identifier) {
return serverIDMap.inverse().get(identifier);
}
public static Set<IGateExpansion> getExpansions() {
Set<IGateExpansion> set = new HashSet<IGateExpansion>();
set.addAll(expansions.values());
return set;
}
public static BiMap<Byte, String> getServerMap() {
return serverIDMap;
}
public static void setClientMap(BiMap<Byte, String> map) {
clientIDMap.clear();
clientIDMap.putAll(map);
}
}

View file

@ -9,6 +9,7 @@ public class PacketIds {
public static final int PIPE_POWER = 4;
public static final int PIPE_ITEMSTACK_REQUEST = 5;
public static final int PIPE_ITEMSTACK = 6;
public static final int PIPE_GATE_EXPANSION_MAP = 7;
public static final int SELECTION_ASSEMBLY_GET = 20;
/** Packet sent to server when a recipe is clicked on in the assembly table */

View file

@ -1051,7 +1051,7 @@ public class BlockGenericPipe extends BlockBuildCraft {
logic.registerBlockIcon(iconRegister);
}
for (IGateExpansion expansion : GateExpansions.expansions.values()) {
for (IGateExpansion expansion : GateExpansions.getExpansions()) {
expansion.registerBlockOverlay(iconRegister);
}

View file

@ -14,18 +14,20 @@ import buildcraft.core.triggers.ActionRedstoneOutput;
import buildcraft.transport.gates.GateDefinition.GateLogic;
import buildcraft.transport.gates.GateDefinition.GateMaterial;
import buildcraft.api.gates.GateExpansionController;
import buildcraft.api.gates.IGateExpansion;
import buildcraft.transport.gates.ItemGate;
import buildcraft.transport.triggers.ActionSignalOutput;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.ForgeDirection;
@ -34,7 +36,7 @@ public final class Gate {
public final Pipe pipe;
public final GateMaterial material;
public final GateLogic logic;
public final Set<GateExpansionController> expansions = new HashSet<GateExpansionController>();
public final BiMap<IGateExpansion, GateExpansionController> expansions = HashBiMap.create();
public ITrigger[] triggers = new ITrigger[8];
public ITriggerParameter[] triggerParameters = new ITriggerParameter[8];
public IAction[] actions = new IAction[8];
@ -72,10 +74,25 @@ public final class Gate {
return triggerParameters[position];
}
public void addGateExpansion(IGateExpansion expansion) {
if (!expansions.containsKey(expansion))
expansions.put(expansion, expansion.makeController(pipe.container));
}
// / SAVING & LOADING
public void writeToNBT(NBTTagCompound data) {
data.setString("material", material.name());
data.setString("logic", logic.name());
NBTTagList exList = new NBTTagList();
for(GateExpansionController con : expansions.values()){
NBTTagCompound conNBT = new NBTTagCompound();
conNBT.setString("type", con.getType().getUniqueIdentifier());
NBTTagCompound conData = new NBTTagCompound();
con.writeToNBT(conData);
conNBT.setTag("data", conData);
exList.appendTag(conNBT);
}
data.setTag("expansions", exList);
for (int i = 0; i < 8; ++i) {
if (triggers[i] != null)
@ -122,7 +139,7 @@ public final class Gate {
// / UPDATING
public void tick() {
for (GateExpansionController expansion : expansions) {
for (GateExpansionController expansion : expansions.values()) {
expansion.tick();
}
}
@ -155,7 +172,7 @@ public final class Gate {
}
public void startResolution() {
for (GateExpansionController expansion : expansions) {
for (GateExpansionController expansion : expansions.values()) {
expansion.startResolution();
}
}
@ -234,7 +251,7 @@ public final class Gate {
}
public boolean resolveAction(IAction action, int count) {
for (GateExpansionController expansion : expansions) {
for (GateExpansionController expansion : expansions.values()) {
if (expansion.resolveAction(action, count))
return true;
}
@ -281,7 +298,7 @@ public final class Gate {
list.add(BuildCraftTransport.triggerYellowSignalInactive);
}
for (GateExpansionController expansion : expansions) {
for (GateExpansionController expansion : expansions.values()) {
expansion.addTriggers(list);
}
@ -308,7 +325,7 @@ public final class Gate {
list.add(BuildCraftTransport.actionYellowSignal);
for (GateExpansionController expansion : expansions) {
for (GateExpansionController expansion : expansions.values()) {
expansion.addActions(list);
}
}

View file

@ -31,6 +31,9 @@ import buildcraft.BuildCraftTransport;
import buildcraft.api.core.IIconProvider;
import buildcraft.api.core.Position;
import buildcraft.api.core.SafeTimeTracker;
import buildcraft.api.gates.GateExpansionController;
import buildcraft.api.gates.GateExpansions;
import buildcraft.api.gates.IGateExpansion;
import buildcraft.api.gates.IOverrideDefaultTriggers;
import buildcraft.api.gates.ITrigger;
import buildcraft.api.power.IPowerReceptor;
@ -52,6 +55,8 @@ import buildcraft.transport.gates.GateDefinition;
import buildcraft.transport.gates.GateFactory;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import java.util.HashSet;
import java.util.Set;
import net.minecraft.server.management.PlayerInstance;
import net.minecraft.world.WorldServer;
@ -63,12 +68,17 @@ public class TileGenericPipe extends TileEntity implements IPowerReceptor, IFlui
public int pipeId = -1;
public int gateMaterial = -1;
public int gateLogic = -1;
public final Set<Byte> expansions = new HashSet<Byte>();
@Override
public void writeData(DataOutputStream data) throws IOException {
data.writeInt(pipeId);
data.writeByte(gateMaterial);
data.writeByte(gateLogic);
data.writeByte(expansions.size());
for (Byte expansion : expansions) {
data.writeByte(expansion);
}
}
@Override
@ -76,6 +86,11 @@ public class TileGenericPipe extends TileEntity implements IPowerReceptor, IFlui
pipeId = data.readInt();
gateMaterial = data.readByte();
gateLogic = data.readByte();
expansions.clear();
int numExp = data.readByte();
for (int i = 0; i < numExp; i++) {
expansions.add(data.readByte());
}
}
}
public final PipeRenderState renderState = new PipeRenderState();
@ -89,6 +104,7 @@ public class TileGenericPipe extends TileEntity implements IPowerReceptor, IFlui
private boolean blockNeighborChange = false;
private boolean refreshRenderState = false;
private boolean pipeBound = false;
private boolean resyncGateExpansions = false;
public boolean redstonePowered = false;
private int[] facadeBlocks = new int[ForgeDirection.VALID_DIRECTIONS.length];
private int[] facadeMeta = new int[ForgeDirection.VALID_DIRECTIONS.length];
@ -123,6 +139,7 @@ public class TileGenericPipe extends TileEntity implements IPowerReceptor, IFlui
coreState.pipeId = nbt.getInteger("pipeId");
pipe = BlockGenericPipe.createPipe(coreState.pipeId);
bindPipe();
if (pipe != null)
pipe.readFromNBT(nbt);
@ -177,8 +194,11 @@ public class TileGenericPipe extends TileEntity implements IPowerReceptor, IFlui
pipe.updateEntity();
if (worldObj.isRemote)
if (worldObj.isRemote) {
if (resyncGateExpansions)
syncGateExpansions();
return;
}
if (blockNeighborChange) {
computeConnections();
@ -362,9 +382,13 @@ public class TileGenericPipe extends TileEntity implements IPowerReceptor, IFlui
bindPipe();
PacketTileState packet = new PacketTileState(this.xCoord, this.yCoord, this.zCoord);
coreState.expansions.clear();
if (pipe != null && pipe.gate != null) {
coreState.gateMaterial = pipe.gate.material.ordinal();
coreState.gateLogic = pipe.gate.logic.ordinal();
for (IGateExpansion ex : pipe.gate.expansions.keySet()) {
coreState.expansions.add(GateExpansions.getServerExpansionID(ex.getUniqueIdentifier()));
}
} else {
coreState.gateMaterial = -1;
coreState.gateLogic = -1;
@ -643,6 +667,8 @@ public class TileGenericPipe extends TileEntity implements IPowerReceptor, IFlui
else if (pipe.gate == null)
pipe.gate = GateFactory.makeGate(pipe, GateDefinition.GateMaterial.fromOrdinal(coreState.gateMaterial), GateDefinition.GateLogic.fromOrdinal(coreState.gateLogic));
syncGateExpansions();
worldObj.markBlockForRenderUpdate(xCoord, yCoord, zCoord);
break;
case 1: {
@ -655,6 +681,21 @@ public class TileGenericPipe extends TileEntity implements IPowerReceptor, IFlui
}
}
private void syncGateExpansions() {
resyncGateExpansions = false;
if (pipe.gate != null && !coreState.expansions.isEmpty()) {
for (byte id : coreState.expansions) {
IGateExpansion ex = GateExpansions.getExpansionClient(id);
if (ex != null) {
if (!pipe.gate.expansions.containsKey(ex))
pipe.gate.addGateExpansion(ex);
} else {
resyncGateExpansions = true;
}
}
}
}
@Override
@SideOnly(Side.CLIENT)
public double getMaxRenderDistanceSquared() {

View file

@ -9,6 +9,7 @@
package buildcraft.transport.gates;
import buildcraft.api.gates.GateExpansionController;
import buildcraft.api.gates.GateExpansions;
import buildcraft.api.gates.IGateExpansion;
import buildcraft.transport.Gate;
import buildcraft.transport.Pipe;
@ -16,6 +17,7 @@ import buildcraft.transport.gates.GateDefinition.GateLogic;
import buildcraft.transport.gates.GateDefinition.GateMaterial;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
/**
*
@ -34,7 +36,7 @@ public class GateFactory {
Gate gate = makeGate(pipe, ItemGate.getMaterial(stack), ItemGate.getLogic(stack));
for (IGateExpansion expansion : ItemGate.getInstalledExpansions(stack)) {
gate.expansions.add(expansion.makeController(pipe.container));
gate.addGateExpansion(expansion);
}
return gate;
@ -91,7 +93,18 @@ public class GateFactory {
NBTTagCompound pulsarTag = nbt.getCompoundTag("Pulser");
GateExpansionController pulsarCon = GateExpansionPulsar.INSTANCE.makeController(pipe.container);
pulsarCon.readFromNBT(pulsarTag);
gate.expansions.add(pulsarCon);
gate.expansions.put(GateExpansionPulsar.INSTANCE, pulsarCon);
}
NBTTagList exList = nbt.getTagList("expansions");
for (int i = 0; i < exList.tagCount(); i++) {
NBTTagCompound conNBT = (NBTTagCompound) exList.tagAt(i);
IGateExpansion ex = GateExpansions.getExpansion(conNBT.getString("type"));
if (ex != null) {
GateExpansionController con = ex.makeController(pipe.container);
con.readFromNBT(conNBT.getCompoundTag("data"));
gate.expansions.put(ex, con);
}
}
return gate;

View file

@ -89,7 +89,7 @@ public class ItemGate extends ItemBuildCraft {
NBTTagList expansionList = nbt.getTagList("ex");
for (int i = 0; i < expansionList.tagCount(); i++) {
NBTTagString exTag = (NBTTagString) expansionList.tagAt(i);
IGateExpansion ex = GateExpansions.expansions.get(exTag.data);
IGateExpansion ex = GateExpansions.getExpansion(exTag.data);
if (ex != null)
expansions.add(ex);
}
@ -111,8 +111,8 @@ public class ItemGate extends ItemBuildCraft {
NBTTagCompound nbt = InvUtils.getItemData(stack);
nbt.setByte("mat", (byte) gate.material.ordinal());
nbt.setByte("logic", (byte) gate.logic.ordinal());
for (GateExpansionController expansion : gate.expansions) {
addGateExpansion(stack, expansion.getType());
for (IGateExpansion expansion : gate.expansions.keySet()) {
addGateExpansion(stack, expansion);
}
return stack;
}
@ -131,7 +131,7 @@ public class ItemGate extends ItemBuildCraft {
if (material == GateMaterial.REDSTONE && logic == GateLogic.OR)
continue;
ItemStack stack = makeGateItem(material, logic);
for (IGateExpansion exp : GateExpansions.expansions.values()) {
for (IGateExpansion exp : GateExpansions.getExpansions()) {
addGateExpansion(stack, exp);
}
itemList.add(stack);
@ -164,7 +164,7 @@ public class ItemGate extends ItemBuildCraft {
logic.registerItemIcon(iconRegister);
}
for (IGateExpansion expansion : GateExpansions.expansions.values()) {
for (IGateExpansion expansion : GateExpansions.getExpansions()) {
expansion.registerItemOverlay(iconRegister);
}

View file

@ -0,0 +1,44 @@
package buildcraft.transport.network;
import buildcraft.api.gates.GateExpansions;
import buildcraft.core.network.BuildCraftPacket;
import buildcraft.core.network.PacketIds;
import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Map;
public class PacketGateExpansionMap extends BuildCraftPacket {
public PacketGateExpansionMap() {
}
@Override
public void writeData(DataOutputStream data) throws IOException {
BiMap<Byte, String> map = GateExpansions.getServerMap();
data.writeByte(map.size());
for (Map.Entry<Byte, String> entry : map.entrySet()) {
data.writeByte(entry.getKey());
data.writeUTF(entry.getValue());
}
}
@Override
public void readData(DataInputStream data) throws IOException {
int numEntries = data.readByte();
BiMap<Byte, String> map = HashBiMap.create(numEntries);
for (int i = 0; i < numEntries; i++) {
byte id = data.readByte();
String identifier = data.readUTF();
map.put(id, identifier);
}
GateExpansions.setClientMap(map);
}
@Override
public int getID() {
return PacketIds.PIPE_GATE_EXPANSION_MAP;
}
}

View file

@ -66,6 +66,11 @@ public class PacketHandlerTransport implements IPacketHandler {
pkt.readData(data);
break;
}
case PacketIds.PIPE_GATE_EXPANSION_MAP: {
PacketGateExpansionMap pkt = new PacketGateExpansionMap();
pkt.readData(data);
break;
}
/**
* SERVER SIDE *

View file

@ -0,0 +1,52 @@
/*
* Copyright (c) SpaceToad, 2011-2012
* http://www.mod-buildcraft.com
*
* BuildCraft is distributed under the terms of the Minecraft Mod Public
* License 1.0, or MMPL. Please check the contents of the license located in
* http://www.mod-buildcraft.com/MMPL-1.0.txt
*/
package buildcraft.transport.network;
import cpw.mods.fml.common.network.IConnectionHandler;
import cpw.mods.fml.common.network.PacketDispatcher;
import cpw.mods.fml.common.network.Player;
import net.minecraft.network.INetworkManager;
import net.minecraft.network.NetLoginHandler;
import net.minecraft.network.packet.NetHandler;
import net.minecraft.network.packet.Packet1Login;
import net.minecraft.server.MinecraftServer;
/**
*
* @author CovertJaguar <http://www.railcraft.info/>
*/
public class TransportConnectionHandler implements IConnectionHandler {
@Override
public void playerLoggedIn(Player player, NetHandler netHandler, INetworkManager manager) {
PacketGateExpansionMap pkt = new PacketGateExpansionMap();
PacketDispatcher.sendPacketToPlayer(pkt.getPacket(), player);
}
@Override
public String connectionReceived(NetLoginHandler netHandler, INetworkManager manager) {
return null;
}
@Override
public void connectionOpened(NetHandler netClientHandler, String server, int port, INetworkManager manager) {
}
@Override
public void connectionOpened(NetHandler netClientHandler, MinecraftServer server, INetworkManager manager) {
}
@Override
public void connectionClosed(INetworkManager manager) {
}
@Override
public void clientLoggedIn(NetHandler clientHandler, INetworkManager manager, Packet1Login login) {
}
}

View file

@ -11,6 +11,7 @@ import buildcraft.BuildCraftCore;
import buildcraft.BuildCraftCore.RenderMode;
import buildcraft.BuildCraftTransport;
import buildcraft.api.gates.GateExpansionController;
import buildcraft.api.gates.IGateExpansion;
import buildcraft.core.CoreConstants;
import buildcraft.core.render.RenderEntityBlock;
import buildcraft.core.render.RenderEntityBlock.RenderInfo;
@ -463,8 +464,8 @@ public class PipeRendererTESR extends TileEntitySpecialRenderer {
if (materialIcon != null)
renderGate(pipe, materialIcon, 1);
for (GateExpansionController expansion : pipe.pipe.gate.expansions) {
renderGate(pipe, expansion.getType().getOverlayBlock(), 2);
for (IGateExpansion expansion : pipe.pipe.gate.expansions.keySet()) {
renderGate(pipe, expansion.getOverlayBlock(), 2);
}
RenderHelper.enableStandardItemLighting();