package joshie.progression.network; import io.netty.buffer.ByteBuf; import joshie.progression.api.ICustomDataBuilder; import joshie.progression.api.ProgressionAPI; import joshie.progression.api.criteria.ICriteria; import joshie.progression.handlers.APICache; import joshie.progression.helpers.MCClientHelper; import joshie.progression.network.core.PenguinPacket; import joshie.progression.player.PlayerTracker; import net.minecraft.block.Block; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.ResourceLocation; import net.minecraftforge.fml.common.network.ByteBufUtils; import net.minecraftforge.fml.relauncher.Side; import java.util.HashMap; import java.util.UUID; @Packet(isSided = true, side = Side.SERVER) public class PacketFireTrigger extends PenguinPacket { private String type; private Object[] data; public PacketFireTrigger() {} public PacketFireTrigger(String type, Object[] data) { this.type = type; this.data = data; } @Override public void toBytes(ByteBuf buf) { ByteBufUtils.writeUTF8String(buf, type); if (data == null || data.length == 0) buf.writeBoolean(false); else { buf.writeBoolean(true); buf.writeInt(data.length); for (Object object : data) { EnumObjectType type = EnumObjectType.getType(object); buf.writeByte(type.ordinal()); //Write the type of object switch (type) { case BOOLEAN: buf.writeBoolean((Boolean) object); break; case BYTE: buf.writeByte((Byte) object); break; case SHORT: buf.writeShort((Short)object); break; case INT: buf.writeInt((Integer) object); break; case LONG: buf.writeLong((Long)object); break; case DOUBLE: buf.writeDouble((Double) object); break; case FLOAT: buf.writeFloat((Float) object); break; case ITEMSTACK: ByteBufUtils.writeItemStack(buf, (ItemStack) object); break; case NBT: ByteBufUtils.writeTag(buf, (NBTTagCompound) object); break; case STRING: ByteBufUtils.writeUTF8String(buf, (String) object); break; case CRITERIA: ByteBufUtils.writeUTF8String(buf, ((ICriteria) object).getUniqueID().toString()); break; case BLOCK: ResourceLocation blockLocation = Block.REGISTRY.getNameForObject((Block) object); ByteBufUtils.writeUTF8String(buf, blockLocation.getResourceDomain()); ByteBufUtils.writeUTF8String(buf, blockLocation.getResourcePath()); break; case ITEM: ResourceLocation itemLocation = Item.REGISTRY.getNameForObject((Item) object); ByteBufUtils.writeUTF8String(buf, itemLocation.getResourceDomain()); ByteBufUtils.writeUTF8String(buf, itemLocation.getResourcePath()); break; case ENTITY: buf.writeInt(((Entity) object).getEntityId()); break; default: break; } } } } @Override public void fromBytes(ByteBuf buf) { type = ByteBufUtils.readUTF8String(buf); if (buf.readBoolean()) { int length = buf.readInt(); data = new Object[length]; for (int i = 0; i < data.length; i++) { EnumObjectType type = EnumObjectType.values()[buf.readByte()]; //Read the type of object switch (type) { case BOOLEAN: data[i] = buf.readBoolean(); break; case BYTE: data[i] = buf.readByte(); break; case SHORT: data[i] = buf.readShort(); break; case INT: data[i] = buf.readInt(); break; case LONG: data[i] = buf.readLong(); break; case DOUBLE: data[i] = buf.readDouble(); break; case FLOAT: data[i] = buf.readFloat(); break; case STRING: data[i] = ByteBufUtils.readUTF8String(buf); break; case ITEMSTACK: data[i] = ByteBufUtils.readItemStack(buf); break; case NBT: data[i] = ByteBufUtils.readTag(buf); break; case CRITERIA: data[i] = APICache.getServerCache().getCriteria(UUID.fromString(ByteBufUtils.readUTF8String(buf))); break; case BLOCK: data[i] = Block.REGISTRY.getObject(new ResourceLocation(ByteBufUtils.readUTF8String(buf), ByteBufUtils.readUTF8String(buf))); break; case ITEM: data[i] = Item.REGISTRY.getObject(new ResourceLocation(ByteBufUtils.readUTF8String(buf), ByteBufUtils.readUTF8String(buf))); break; case ENTITY: data[i] = MCClientHelper.getMinecraft().theWorld.getEntityByID(buf.readInt()); break; default: break; } } } } private static enum EnumObjectType { BOOLEAN, BYTE, SHORT, INT, LONG, DOUBLE, FLOAT, STRING, ITEMSTACK, NBT, CRITERIA, BLOCK, ITEM, ENTITY; public static EnumObjectType getType(Object object) { if (object.getClass() == boolean.class || object instanceof Boolean) return BOOLEAN; if (object.getClass() == byte.class || object instanceof Byte) return BYTE; if (object.getClass() == short.class || object instanceof Short) return SHORT; if (object.getClass() == int.class || object instanceof Integer) return INT; if (object.getClass() == long.class || object instanceof Long) return LONG; if (object.getClass() == double.class || object instanceof Double) return DOUBLE; if (object.getClass() == float.class || object instanceof Float) return FLOAT; if (object instanceof String) return STRING; if (object instanceof ItemStack) return ITEMSTACK; if (object instanceof NBTTagCompound) return NBT; if (object instanceof ICriteria) return CRITERIA; if (object instanceof Block) return BLOCK; if (object instanceof Item) return ITEM; if (object instanceof Entity) return ENTITY; return null; } } public static HashMap<String, ICustomDataBuilder> handlers = new HashMap(); @Override public void handlePacket(EntityPlayer player) { ICustomDataBuilder builder = handlers.get(type); if (builder != null) { data = builder.getObjects(player, type, data); } if (type.equals("complete")) PlayerTracker.getServerPlayer(player).getMappings().forceComplete((ICriteria)data[0]); else ProgressionAPI.registry.fireTrigger(player, type, data); } }