add robot wearable support, entity API improvements, robot packet optimizations, etc

This commit is contained in:
Adrian 2015-05-06 23:14:00 +02:00
parent 81ac1bc77d
commit 99432bb11a
11 changed files with 265 additions and 107 deletions

View file

@ -12,6 +12,8 @@ import java.util.EnumMap;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedDeque;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.network.NetHandlerPlayServer;
@ -26,6 +28,7 @@ import cpw.mods.fml.common.network.FMLOutboundHandler.OutboundTarget;
import cpw.mods.fml.relauncher.Side;
import buildcraft.core.DefaultProps;
import buildcraft.core.lib.network.Packet;
import net.minecraft.world.WorldServer;
public class BuildCraftMod {
private static PacketSender sender = new PacketSender();
@ -58,6 +61,27 @@ public class BuildCraftMod {
}
}
class EntitySendRequest extends SendRequest {
Entity entity;
EntitySendRequest(BuildCraftMod source, Packet packet, Entity entity) {
super(source, packet);
this.entity = entity;
}
boolean isValid(EntityPlayer player) {
if (player.worldObj.equals(entity.worldObj)) {
if (player.worldObj instanceof WorldServer) {
return ((WorldServer) player.worldObj).getEntityTracker().getTrackingPlayers(entity).contains(player);
} else {
return true;
}
} else {
return false;
}
}
}
class WorldSendRequest extends SendRequest {
final int dimensionId;
@ -149,6 +173,10 @@ public class BuildCraftMod {
public void sendToWorld(Packet packet, World world) {
sender.add(new WorldSendRequest(this, packet, world.provider.dimensionId));
}
public void sendToEntity(Packet packet, Entity entity) {
sender.add(new EntitySendRequest(this, packet, entity));
}
public void sendToPlayer(EntityPlayer entityplayer, Packet packet) {
sender.add(new PlayerSendRequest(this, packet, entityplayer));

View file

@ -26,7 +26,8 @@ public class ChannelHandler extends FMLIndexedMessageToMessageCodec<Packet> {
addDiscriminator(5, PacketGuiWidget.class);
addDiscriminator(6, PacketUpdate.class);
addDiscriminator(7, PacketCommand.class);
maxDiscriminator = 8;
addDiscriminator(8, PacketEntityUpdate.class);
maxDiscriminator = 9;
}
public void registerPacketType(Class<? extends Packet> packetType) {

View file

@ -0,0 +1,53 @@
/**
* Copyright (c) 2011-2015, SpaceToad and the BuildCraft Team
* 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.core.lib.network;
import buildcraft.api.core.ISerializable;
import buildcraft.core.network.PacketIds;
import io.netty.buffer.ByteBuf;
import net.minecraft.entity.Entity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
public class PacketEntityUpdate extends PacketUpdate {
public int entityId;
public PacketEntityUpdate() {
super(PacketIds.ENTITY_UPDATE);
}
public PacketEntityUpdate(ISerializable payload) {
this(PacketIds.ENTITY_UPDATE, payload);
}
public PacketEntityUpdate(int packetId, ISerializable payload) {
super(packetId, payload);
Entity entity = (Entity) payload;
entityId = entity.getEntityId();
}
@Override
public void writeIdentificationData(ByteBuf data) {
data.writeInt(entityId);
}
@Override
public void readIdentificationData(ByteBuf data) {
entityId = data.readInt();
}
public boolean targetExists(World world) {
return world.getEntityByID(entityId) != null;
}
public Entity getTarget(World world) {
return world.getEntityByID(entityId);
}
}

View file

@ -12,6 +12,7 @@ import java.io.IOException;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.network.INetHandler;
import net.minecraft.tileentity.TileEntity;
@ -41,6 +42,23 @@ public class PacketHandler extends SimpleChannelInboundHandler<Packet> {
tile.readData(packet.stream);
}
private void onEntityUpdate(EntityPlayer player, PacketEntityUpdate packet) throws IOException {
World world = player.worldObj;
if (!packet.targetExists(world)) {
return;
}
Entity entity = packet.getTarget(world);
if (!(entity instanceof ISerializable)) {
return;
}
ISerializable payload = (ISerializable) entity;
payload.readData(packet.stream);
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, Packet packet) {
try {
@ -55,6 +73,11 @@ public class PacketHandler extends SimpleChannelInboundHandler<Packet> {
break;
}
case PacketIds.ENTITY_UPDATE: {
onEntityUpdate(player, (PacketEntityUpdate) packet);
break;
}
case PacketIds.COMMAND: {
((PacketCommand) packet).handle(player);
break;

View file

@ -8,27 +8,46 @@
*/
package buildcraft.core.lib.network;
import io.netty.buffer.ByteBuf;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import buildcraft.api.core.ISerializable;
import buildcraft.core.network.PacketIds;
public class PacketTileUpdate extends PacketUpdate {
public int posX;
public int posY;
public int posZ;
public PacketTileUpdate() {
super(PacketIds.TILE_UPDATE);
}
public PacketTileUpdate(ISerializable tile) {
super(PacketIds.TILE_UPDATE);
this(PacketIds.TILE_UPDATE, tile);
}
public PacketTileUpdate(int packetId, ISerializable tile) {
super(packetId, tile);
TileEntity entity = (TileEntity) tile;
posX = entity.xCoord;
posY = entity.yCoord;
posZ = entity.zCoord;
}
this.isChunkDataPacket = true;
this.payload = tile;
@Override
public void writeIdentificationData(ByteBuf data) {
data.writeInt(posX);
data.writeShort(posY);
data.writeInt(posZ);
}
@Override
public void readIdentificationData(ByteBuf data) {
posX = data.readInt();
posY = data.readShort();
posZ = data.readInt();
}
public boolean targetExists(World world) {

View file

@ -11,11 +11,7 @@ package buildcraft.core.lib.network;
import io.netty.buffer.ByteBuf;
import buildcraft.api.core.ISerializable;
public class PacketUpdate extends Packet {
public int posX;
public int posY;
public int posZ;
public abstract class PacketUpdate extends Packet {
public ByteBuf stream;
public ISerializable payload;
@ -25,16 +21,8 @@ public class PacketUpdate extends Packet {
}
public PacketUpdate(int packetId, ISerializable payload) {
this(packetId, 0, 0, 0, payload);
}
public PacketUpdate(int packetId, int posX, int posY, int posZ, ISerializable payload) {
this(packetId);
this.posX = posX;
this.posY = posY;
this.posZ = posZ;
this.payload = payload;
}
@ -46,25 +34,25 @@ public class PacketUpdate extends Packet {
@Override
public void writeData(ByteBuf data) {
data.writeByte(packetId);
data.writeInt(posX);
data.writeShort(posY);
data.writeInt(posZ);
writeIdentificationData(data);
if (payload != null) {
payload.writeData(data);
}
}
public abstract void writeIdentificationData(ByteBuf data);
@Override
public void readData(ByteBuf data) {
packetId = data.readByte();
posX = data.readInt();
posY = data.readShort();
posZ = data.readInt();
readIdentificationData(data);
stream = data; // for further reading
}
public abstract void readIdentificationData(ByteBuf data);
@Override
public int getID() {
return packetId;

View file

@ -17,6 +17,7 @@ public final 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 ENTITY_UPDATE = 7;
public static final int DIAMOND_PIPE_SELECT = 31;
public static final int EMERALD_PIPE_SELECT = 32;

View file

@ -12,6 +12,8 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.WeakHashMap;
import buildcraft.api.robots.*;
import io.netty.buffer.ByteBuf;
import net.minecraft.client.Minecraft;
import net.minecraft.enchantment.EnchantmentHelper;
@ -19,16 +21,12 @@ import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemArmor;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EntityDamageSource;
import net.minecraft.util.IIcon;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.StatCollector;
import net.minecraft.util.Vec3;
import net.minecraft.util.*;
import net.minecraft.world.World;
import cpw.mods.fml.common.registry.IEntityAdditionalSpawnData;
import cpw.mods.fml.relauncher.Side;
@ -49,10 +47,6 @@ import buildcraft.api.boards.RedstoneBoardRobotNBT;
import buildcraft.api.core.BCLog;
import buildcraft.api.core.BlockIndex;
import buildcraft.api.core.IZone;
import buildcraft.api.robots.AIRobot;
import buildcraft.api.robots.DockingStation;
import buildcraft.api.robots.EntityRobotBase;
import buildcraft.api.robots.RobotManager;
import buildcraft.api.statements.StatementSlot;
import buildcraft.api.tiles.IDebuggable;
import buildcraft.core.DefaultProps;
@ -98,6 +92,7 @@ public class EntityRobot extends EntityRobotBase implements
public long lastUpdateTime = 0;
private DockingStation currentDockingStation;
private List<ItemStack> wearables = new ArrayList<ItemStack>();
private boolean needsUpdate = false;
private ItemStack[] inv = new ItemStack[4];
@ -355,35 +350,9 @@ public class EntityRobot extends EntityRobotBase implements
energySpendPerCycle * 0.075F < 1 ? 1 : energySpendPerCycle * 0.075F));
}
public void setRegularBoundingBox() {
width = 0.5F;
height = 0.5F;
if (laser.isVisible) {
boundingBox.minX = Math.min(posX, laser.tail.x);
boundingBox.minY = Math.min(posY, laser.tail.y);
boundingBox.minZ = Math.min(posZ, laser.tail.z);
boundingBox.maxX = Math.max(posX, laser.tail.x);
boundingBox.maxY = Math.max(posY, laser.tail.y);
boundingBox.maxZ = Math.max(posZ, laser.tail.z);
boundingBox.minX--;
boundingBox.minY--;
boundingBox.minZ--;
boundingBox.maxX++;
boundingBox.maxY++;
boundingBox.maxZ++;
} else {
boundingBox.minX = posX - 0.25F;
boundingBox.minY = posY - 0.25F;
boundingBox.minZ = posZ - 0.25F;
boundingBox.maxX = posX + 0.25F;
boundingBox.maxY = posY + 0.25F;
boundingBox.maxZ = posZ + 0.25F;
}
@Override
public AxisAlignedBB getBoundingBox() {
return AxisAlignedBB.getBoundingBox(posX - 0.25F, posY - 0.25F, posZ - 0.25F, posX + 0.25F, posY + 0.25F, posZ + 0.25F);
}
public void setNullBoundingBox() {
@ -404,16 +373,24 @@ public class EntityRobot extends EntityRobotBase implements
motionY = 0F;
motionZ = 0F;
setNullBoundingBox ();
setNullBoundingBox();
}
@Override
public void writeSpawnData(ByteBuf data) {
data.writeByte(wearables.size());
for (ItemStack s : wearables) {
NetworkUtils.writeStack(data, s);
}
}
@Override
public void readSpawnData(ByteBuf data) {
int amount = data.readUnsignedByte();
while (amount > 0) {
wearables.add(NetworkUtils.readStack(data));
amount--;
}
init();
}
@ -496,6 +473,18 @@ public class EntityRobot extends EntityRobotBase implements
}
}
if (wearables.size() > 0) {
NBTTagList wearableList = new NBTTagList();
for (int i = 0; i < wearables.size(); i++) {
NBTTagCompound item = new NBTTagCompound();
wearables.get(i).writeToNBT(item);
wearableList.appendTag(item);
}
nbt.setTag("wearables", wearableList);
}
nbt.setTag("originalBoardNBT", originalBoardNBT);
NBTTagCompound ai = new NBTTagCompound();
@ -540,6 +529,14 @@ public class EntityRobot extends EntityRobotBase implements
battery.readFromNBT(nbt.getCompoundTag("battery"));
wearables.clear();
if (nbt.hasKey("wearables")) {
NBTTagList list = nbt.getTagList("wearables", 10);
for (int i = 0; i < list.tagCount(); i++) {
wearables.add(ItemStack.loadItemStackFromNBT(list.getCompoundTagAt(i)));
}
}
if (nbt.hasKey("itemInUse")) {
itemInUse = ItemStack.loadItemStackFromNBT(nbt.getCompoundTag("itemInUse"));
itemActive = nbt.getBoolean("itemActive");
@ -686,12 +683,12 @@ public class EntityRobot extends EntityRobotBase implements
}
public void updateClientSlot(final int slot) {
BuildCraftCore.instance.sendToWorld(new PacketCommand(this, "clientSetInventory", new CommandWriter() {
BuildCraftCore.instance.sendToEntity(new PacketCommand(this, "clientSetInventory", new CommandWriter() {
public void write(ByteBuf data) {
data.writeShort(slot);
NetworkUtils.writeStack(data, inv[slot]);
}
}), worldObj);
}), this);
}
@Override
@ -722,22 +719,22 @@ public class EntityRobot extends EntityRobotBase implements
@Override
public void setItemInUse(ItemStack stack) {
itemInUse = stack;
BuildCraftCore.instance.sendToWorld(new PacketCommand(this, "clientSetItemInUse", new CommandWriter() {
BuildCraftCore.instance.sendToEntity(new PacketCommand(this, "clientSetItemInUse", new CommandWriter() {
public void write(ByteBuf data) {
NetworkUtils.writeStack(data, itemInUse);
}
}), worldObj);
}), this);
}
private void setSteamDirection(final int x, final int y, final int z) {
if (!worldObj.isRemote) {
BuildCraftCore.instance.sendToWorld(new PacketCommand(this, "setSteamDirection", new CommandWriter() {
BuildCraftCore.instance.sendToEntity(new PacketCommand(this, "setSteamDirection", new CommandWriter() {
public void write(ByteBuf data) {
data.writeInt(x);
data.writeShort(y);
data.writeInt(z);
}
}), worldObj);
}), this);
} else {
Vec3 v = Vec3.createVectorHelper(x, y, z);
v = v.normalize();
@ -769,6 +766,14 @@ public class EntityRobot extends EntityRobotBase implements
}
} else if ("setSteamDirection".equals(command)) {
setSteamDirection(stream.readInt(), stream.readShort(), stream.readInt());
} else if ("syncWearables".equals(command)) {
wearables.clear();
int amount = stream.readUnsignedByte();
while (amount > 0) {
wearables.add(NetworkUtils.readStack(stream));
amount--;
}
}
} else if (side.isServer()) {
EntityPlayer p = (EntityPlayer) sender;
@ -847,11 +852,11 @@ public class EntityRobot extends EntityRobotBase implements
public void setItemActive(final boolean isActive) {
if (isActive != itemActive) {
itemActive = isActive;
BuildCraftCore.instance.sendToWorld(new PacketCommand(this, "setItemActive", new CommandWriter() {
BuildCraftCore.instance.sendToEntity(new PacketCommand(this, "setItemActive", new CommandWriter() {
public void write(ByteBuf data) {
data.writeBoolean(isActive);
}
}), worldObj);
}), this);
}
}
@ -975,18 +980,49 @@ public class EntityRobot extends EntityRobotBase implements
@Override
protected boolean interact(EntityPlayer player) {
ItemStack stack = player.getCurrentEquippedItem();
if (player.isSneaking() && stack != null && stack.getItem() == BuildCraftCore.wrenchItem) {
if (stack == null || stack.getItem() == null) {
return super.interact(player);
}
if (player.isSneaking() && stack.getItem() == BuildCraftCore.wrenchItem) {
if (!worldObj.isRemote) {
convertToItems();
} else {
((ItemWrench) stack.getItem()).wrenchUsed(player, 0, 0, 0);
}
return true;
} else if (wearables.size() < 8 && stack.getItem() instanceof ItemArmor && ((ItemArmor) stack.getItem()).armorType == 0) {
if (!worldObj.isRemote) {
wearables.add(stack.splitStack(1));
syncWearablesToClient();
} else {
player.swingItem();
}
return true;
} else if (wearables.size() < 8 && stack.getItem() instanceof IRobotOverlayItem && ((IRobotOverlayItem) stack.getItem()).isValidRobotOverlay(stack)) {
if (!worldObj.isRemote) {
wearables.add(stack.splitStack(1));
syncWearablesToClient();
} else {
player.swingItem();
}
return true;
} else {
return super.interact(player);
}
}
private void syncWearablesToClient() {
BuildCraftCore.instance.sendToEntity(new PacketCommand(this, "syncWearables", new CommandWriter() {
public void write(ByteBuf data) {
data.writeByte(wearables.size());
for (ItemStack s : wearables) {
NetworkUtils.writeStack(data, s);
}
}
}), this);
}
private List<ItemStack> getDrops() {
List<ItemStack> drops = new ArrayList<ItemStack>();
ItemStack robotStack = new ItemStack(BuildCraftRobotics.robotItem);
@ -1001,6 +1037,7 @@ public class EntityRobot extends EntityRobotBase implements
drops.add(element);
}
}
drops.addAll(wearables);
return drops;
}
@ -1203,4 +1240,8 @@ public class EntityRobot extends EntityRobotBase implements
return energyReceived;
}
public List<ItemStack> getWearables() {
return wearables;
}
}

View file

@ -0,0 +1,6 @@
package buildcraft.robotics.network;
import buildcraft.core.lib.network.PacketHandler;
public class PacketHandlerRobotics extends PacketHandler {
}

View file

@ -9,6 +9,10 @@
package buildcraft.robotics.render;
import java.util.Date;
import buildcraft.api.robots.IRobotOverlayItem;
import net.minecraft.client.renderer.entity.RenderBiped;
import net.minecraft.item.ItemArmor;
import org.lwjgl.opengl.GL11;
import net.minecraft.client.model.ModelBase;
import net.minecraft.client.model.ModelRenderer;
@ -41,7 +45,9 @@ public class RenderRobot extends Render implements IItemRenderer {
private ModelBase model = new ModelBase() {
};
private ModelRenderer box;
private ModelBase modelHelmet = new ModelBase() {
};
private ModelRenderer box, helmetBox;
public RenderRobot() {
customRenderItem = new RenderItem() {
@ -59,9 +65,10 @@ public class RenderRobot extends Render implements IItemRenderer {
box = new ModelRenderer(model, 0, 0);
box.addBox(-4F, -4F, -4F, 8, 8, 8);
box.rotationPointX = 0;
box.rotationPointY = 0;
box.rotationPointZ = 0;
box.setRotationPoint(0.0F, 0.0F, 0.0F);
helmetBox = new ModelRenderer(modelHelmet, 0, 0);
helmetBox.addBox(-4F, -4F, -4F, 8, 8, 8);
helmetBox.setRotationPoint(0.0F, 0.0F, 0.0F);
}
@Override
@ -151,6 +158,10 @@ public class RenderRobot extends Render implements IItemRenderer {
float storagePercent = (float) robot.getBattery().getEnergyStored() / (float) robot.getBattery().getMaxEnergyStored();
doRenderRobot(1F / 16F, renderManager.renderEngine, storagePercent, robot.isActive());
}
for (ItemStack s : robot.getWearables()) {
doRenderWearable(robot, renderManager.renderEngine, s);
}
GL11.glPopMatrix();
}
@ -206,6 +217,19 @@ public class RenderRobot extends Render implements IItemRenderer {
GL11.glPopMatrix();
}
private void doRenderWearable(EntityRobot entity, TextureManager textureManager, ItemStack wearable) {
if (wearable.getItem() instanceof IRobotOverlayItem) {
((IRobotOverlayItem) wearable.getItem()).renderRobotOverlay(wearable, textureManager);
} else if (wearable.getItem() instanceof ItemArmor) {
GL11.glPushMatrix();
GL11.glScalef(1.125F, 1.125F, 1.125F);
GL11.glRotatef(180F, 0, 0, 1);
textureManager.bindTexture(RenderBiped.getArmorResource(entity, wearable, 0, null));
helmetBox.render(1 / 16F);
GL11.glPopMatrix();
}
}
private void doRenderRobot(float factor, TextureManager texManager, float storagePercent, boolean isAsleep) {
box.render(factor);

View file

@ -8,9 +8,9 @@
*/
package buildcraft.silicon.network;
import buildcraft.core.lib.network.PacketHandler;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.network.INetHandler;
import net.minecraft.tileentity.TileEntity;
@ -21,16 +21,14 @@ import buildcraft.core.lib.network.PacketSlotChange;
import buildcraft.core.network.PacketIds;
import buildcraft.core.proxy.CoreProxy;
import buildcraft.silicon.TileAdvancedCraftingTable;
import buildcraft.silicon.TileAssemblyTable;
@Sharable
public class PacketHandlerSilicon extends SimpleChannelInboundHandler<Packet> {
public class PacketHandlerSilicon extends PacketHandler {
@Override
protected void channelRead0(ChannelHandlerContext ctx, Packet packet) {
protected void channelRead0(ChannelHandlerContext ctx, Packet packet) {
super.channelRead0(ctx, packet);
try {
INetHandler netHandler = ctx.channel().attr(NetworkRegistry.NET_HANDLER).get();
EntityPlayer player = CoreProxy.proxy.getPlayerFromNetHandler(netHandler);
int packetID = packet.getID();
@ -39,30 +37,13 @@ public class PacketHandlerSilicon extends SimpleChannelInboundHandler<Packet> {
case PacketIds.ADVANCED_WORKBENCH_SETSLOT:
onAdvancedWorkbenchSet(player, (PacketSlotChange) packet);
break;
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
private TileAssemblyTable getAssemblyTable(World world, int x, int y, int z) {
if (!world.blockExists(x, y, z)) {
return null;
}
TileEntity tile = world.getTileEntity(x, y, z);
if (!(tile instanceof TileAssemblyTable)) {
return null;
}
return (TileAssemblyTable) tile;
}
private TileAdvancedCraftingTable getAdvancedWorkbench(World world, int x, int y, int z) {
if (!world.blockExists(x, y, z)) {
return null;
}
@ -75,14 +56,7 @@ public class PacketHandlerSilicon extends SimpleChannelInboundHandler<Packet> {
return (TileAdvancedCraftingTable) tile;
}
/**
* Sets the packet into the advanced workbench
*
* @param player
* @param packet1
*/
private void onAdvancedWorkbenchSet(EntityPlayer player, PacketSlotChange packet1) {
TileAdvancedCraftingTable tile = getAdvancedWorkbench(player.worldObj, packet1.posX, packet1.posY, packet1.posZ);
if (tile == null) {
return;