added render code for builder robots, for #1908

This commit is contained in:
SpaceToad 2014-07-10 07:15:40 +02:00
parent addad59d08
commit 87c7c9043f
12 changed files with 252 additions and 96 deletions

View file

@ -31,7 +31,7 @@ import buildcraft.core.blueprints.IBuilingItem;
public class BuildingItem implements IBuilingItem {
private static int ITEMS_SPACE = 2;
public static int ITEMS_SPACE = 2;
@NetworkData
public Position origin, destination;

View file

@ -10,10 +10,7 @@ package buildcraft.builders;
import org.lwjgl.opengl.GL11;
import net.minecraft.client.renderer.entity.RenderItem;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.tileentity.TileEntity;
import buildcraft.builders.urbanism.RenderBoxProvider;
@ -23,23 +20,7 @@ import buildcraft.core.render.RenderLaser;
public class RenderBuilder extends RenderBoxProvider {
private final EntityItem dummyEntityItem = new EntityItem(null);
private final RenderItem customRenderItem;
public RenderBuilder () {
customRenderItem = new RenderItem() {
@Override
public boolean shouldBob() {
return false;
}
@Override
public boolean shouldSpreadItems() {
return false;
}
};
customRenderItem.setRenderManager(RenderManager.instance);
}
private final RenderBuildingItems renderItems = new RenderBuildingItems();
@Override
public void renderTileEntityAt(TileEntity tileentity, double x, double y, double z, float f) {
@ -74,42 +55,8 @@ public class RenderBuilder extends RenderBoxProvider {
//GL11.glEnable(GL11.GL_LIGHTING);
GL11.glPopAttrib();
GL11.glPopMatrix();
}
GL11.glPushMatrix();
GL11.glTranslated(x, y, z);
GL11.glTranslated(-tileentity.xCoord, -tileentity.yCoord, -tileentity.zCoord);
if (builder.getBuilders() != null) {
for (BuildingItem i : builder.getBuilders()) {
doRenderItem(i, 1.0F);
}
}
GL11.glPopMatrix();
}
public void doRenderItem(BuildingItem i, float light) {
if (i == null) {
return;
}
i.displayUpdate();
for (StackAtPosition s : i.getStacks()) {
if (s.display) {
float renderScale = 0.7f;
GL11.glPushMatrix();
GL11.glTranslatef((float) s.pos.x, (float) s.pos.y,
(float) s.pos.z);
GL11.glTranslatef(0, 0.25F, 0);
GL11.glScalef(renderScale, renderScale, renderScale);
dummyEntityItem.setEntityItemStack(s.stack);
customRenderItem.doRender(dummyEntityItem, 0, 0, 0, 0, 0);
GL11.glPopMatrix();
}
renderItems.render(tileentity, x, y, z);
}
}

View file

@ -0,0 +1,78 @@
/**
* Copyright (c) 2011-2014, 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.builders;
import org.lwjgl.opengl.GL11;
import net.minecraft.client.renderer.entity.RenderItem;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.tileentity.TileEntity;
public class RenderBuildingItems {
private final EntityItem dummyEntityItem = new EntityItem(null);
private final RenderItem customRenderItem;
public RenderBuildingItems () {
customRenderItem = new RenderItem() {
@Override
public boolean shouldBob() {
return false;
}
@Override
public boolean shouldSpreadItems() {
return false;
}
};
customRenderItem.setRenderManager(RenderManager.instance);
}
public void render(TileEntity tile, double x, double y, double z) {
IBuildingItemsProvider provider = (IBuildingItemsProvider) tile;
GL11.glPushMatrix();
GL11.glTranslated(x, y, z);
GL11.glTranslated(-tile.xCoord, -tile.yCoord, -tile.zCoord);
if (provider.getBuilders() != null) {
for (BuildingItem i : provider.getBuilders()) {
doRenderItem(i, 1.0F);
}
}
GL11.glPopMatrix();
}
private void doRenderItem(BuildingItem i, float light) {
if (i == null) {
return;
}
i.displayUpdate();
for (StackAtPosition s : i.getStacks()) {
if (s.display) {
float renderScale = 0.7f;
GL11.glPushMatrix();
GL11.glTranslatef((float) s.pos.x, (float) s.pos.y,
(float) s.pos.z);
GL11.glTranslatef(0, 0.25F, 0);
GL11.glScalef(renderScale, renderScale, renderScale);
dummyEntityItem.setEntityItemStack(s.stack);
customRenderItem.doRender(dummyEntityItem, 0, 0, 0, 0, 0);
GL11.glPopMatrix();
}
}
}
}

View file

@ -15,15 +15,17 @@ import net.minecraft.client.model.ModelRenderer;
import net.minecraft.client.renderer.entity.RenderItem;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.client.renderer.tileentity.TileEntityRendererDispatcher;
import net.minecraft.client.renderer.tileentity.TileEntitySpecialRenderer;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import buildcraft.builders.urbanism.RenderBoxProvider;
import buildcraft.core.EntityLaser;
import buildcraft.core.render.RenderLaser;
public class RenderConstructionMarker extends TileEntitySpecialRenderer {
public class RenderConstructionMarker extends RenderBoxProvider {
private final RenderBuildingItems renderItems = new RenderBuildingItems();
private final EntityItem dummyEntityItem = new EntityItem(null);
private final RenderItem customRenderItem;
@ -55,6 +57,8 @@ public class RenderConstructionMarker extends TileEntitySpecialRenderer {
@Override
public void renderTileEntityAt(TileEntity tileentity, double x, double y, double z, float f) {
super.renderTileEntityAt(tileentity, x, y, z, f);
TileConstructionMarker marker = (TileConstructionMarker) tileentity;
if (marker != null) {
@ -87,6 +91,8 @@ public class RenderConstructionMarker extends TileEntitySpecialRenderer {
//GL11.glEnable(GL11.GL_LIGHTING);
GL11.glPopAttrib();
GL11.glPopMatrix();
renderItems.render(tileentity, x, y, z);
}
}

View file

@ -13,11 +13,15 @@ import java.util.HashSet;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.AxisAlignedBB;
import net.minecraftforge.common.util.ForgeDirection;
import buildcraft.api.core.NetworkData;
import buildcraft.api.core.Position;
import buildcraft.core.Box;
import buildcraft.core.Box.Kind;
import buildcraft.core.IBoxProvider;
import buildcraft.core.LaserData;
import buildcraft.core.TileBuildCraft;
import buildcraft.core.blueprints.Blueprint;
@ -26,9 +30,10 @@ import buildcraft.core.blueprints.BptBuilderBlueprint;
import buildcraft.core.blueprints.BptContext;
import buildcraft.core.network.RPC;
import buildcraft.core.network.RPCHandler;
import buildcraft.core.network.RPCMessageInfo;
import buildcraft.core.network.RPCSide;
public class TileConstructionMarker extends TileBuildCraft implements IBuildingItemsProvider {
public class TileConstructionMarker extends TileBuildCraft implements IBuildingItemsProvider, IBoxProvider {
public static HashSet<TileConstructionMarker> currentMarkers = new HashSet<TileConstructionMarker>();
@ -40,16 +45,42 @@ public class TileConstructionMarker extends TileBuildCraft implements IBuildingI
@NetworkData
public ItemStack itemBlueprint;
@NetworkData
public Box box = new Box();
public BptBuilderBase bluePrintBuilder;
public BptContext bptContext;
private ArrayList<BuildingItem> buildersInAction = new ArrayList<BuildingItem>();
private NBTTagCompound initNBT;
@Override
public void initialize() {
box.kind = Kind.STRIPES;
if (worldObj.isRemote) {
RPCHandler.rpcServer(this, "uploadBuildersInAction");
}
}
@Override
public void updateEntity() {
super.updateEntity();
BuildingItem toRemove = null;
for (BuildingItem i : buildersInAction) {
i.update();
if (i.isDone) {
toRemove = i;
}
}
if (toRemove != null) {
buildersInAction.remove(toRemove);
}
if (worldObj.isRemote) {
return;
}
@ -58,6 +89,8 @@ public class TileConstructionMarker extends TileBuildCraft implements IBuildingI
bluePrintBuilder = new BptBuilderBlueprint((Blueprint) ItemBlueprint.loadBlueprint(itemBlueprint),
worldObj, xCoord, yCoord, zCoord);
bptContext = bluePrintBuilder.getContext();
box.initialize(bluePrintBuilder);
sendNetworkUpdate();
}
if (laser == null && direction != ForgeDirection.UNKNOWN) {
@ -155,7 +188,26 @@ public class TileConstructionMarker extends TileBuildCraft implements IBuildingI
}
@RPC(RPCSide.CLIENT)
public void launchItem(BuildingItem item) {
private void launchItem(BuildingItem item) {
buildersInAction.add(item);
}
@Override
public Box getBox() {
return box;
}
@Override
public AxisAlignedBB getRenderBoundingBox() {
Box renderBox = new Box(this).extendToEncompass(box);
return renderBox.expand(50).getBoundingBox();
}
@RPC(RPCSide.SERVER)
private void uploadBuildersInAction(RPCMessageInfo info) {
for (BuildingItem i : buildersInAction) {
RPCHandler.rpcPlayer(info.sender, this, "launchItem", i);
}
}
}

View file

@ -71,7 +71,7 @@ public abstract class BptBuilderBase implements IAreaProvider {
BuildingSlot slot = getNextBlock(world, builder);
return buildSlot(world, builder, slot, x, y, z);
return buildSlot(world, builder, slot, x + 0.5F, y + 0.5F, z + 0.5F);
}
public boolean buildSlot(World world, IBuildingItemsProvider builder, BuildingSlot slot, double x, double y,
@ -83,7 +83,7 @@ public abstract class BptBuilderBase implements IAreaProvider {
if (slot != null) {
BuildingItem i = new BuildingItem();
i.origin = new Position(x + 0.5, y + 0.5, z + 0.5);
i.origin = new Position(x, y, z);
i.destination = slot.getDestination();
i.slotToBuild = slot;
i.context = getContext();
@ -166,9 +166,7 @@ public abstract class BptBuilderBase implements IAreaProvider {
return done && builder.getBuilders().size() == 0;
}
protected boolean setupForDestroy (TileAbstractBuilder builder, IBuilderContext context, BuildingSlotBlock slot) {
LinkedList<ItemStack> result = new LinkedList<ItemStack>();
private int getHardness(BuildingSlotBlock slot) {
int hardness = (int) context
.world()
.getBlock(slot.x, slot.y, slot.z)
@ -177,16 +175,28 @@ public abstract class BptBuilderBase implements IAreaProvider {
hardness *= 2;
if (builder.energyAvailable() < hardness * SchematicRegistry.BREAK_ENERGY) {
return false;
} else {
builder.consumeEnergy(hardness * SchematicRegistry.BREAK_ENERGY);
return hardness;
}
for (int i = 0; i < hardness; ++i) {
slot.addStackConsumed(new ItemStack(BuildCraftBuilders.buildToolBlock));
}
protected final boolean canDestroy(TileAbstractBuilder builder, IBuilderContext context, BuildingSlotBlock slot) {
LinkedList<ItemStack> result = new LinkedList<ItemStack>();
return true;
int hardness = getHardness(slot);
return builder.energyAvailable() >= hardness * SchematicRegistry.BREAK_ENERGY;
}
public void consumeEnergyToDestroy(TileAbstractBuilder builder, BuildingSlotBlock slot) {
int hardness = getHardness(slot);
builder.consumeEnergy(hardness * SchematicRegistry.BREAK_ENERGY);
}
public void createDestroyItems(BuildingSlotBlock slot) {
int hardness = getHardness(slot);
for (int i = 0; i < hardness; ++i) {
slot.addStackConsumed(new ItemStack(BuildCraftBuilders.buildToolBlock));
}
}

View file

@ -348,17 +348,23 @@ public class BptBuilderBlueprint extends BptBuilderBase {
clearedLocations.add(new BlockIndex(slot.x,
slot.y, slot.z));
} else {
if (builder != null && setupForDestroy(builder, context, slot)) {
if (builder == null) {
createDestroyItems(slot);
return slot;
} else if (canDestroy(builder, context, slot)) {
consumeEnergyToDestroy(builder, slot);
createDestroyItems(slot);
iterator.remove();
clearedLocations.add(new BlockIndex(slot.x,
slot.y, slot.z));
return slot;
} else {
return slot;
}
}
} else if (!slot.schematic.doNotBuild()) {
if (builder != null && checkRequirements(builder, slot.schematic)) {
if (builder == null) {
return slot;
} else if (checkRequirements(builder, slot.schematic)) {
// At this stage, regardless of the fact that the
// block can actually be built or not, we'll try.
// When the item reaches the actual block, we'll
@ -371,8 +377,6 @@ public class BptBuilderBlueprint extends BptBuilderBase {
builtLocations.add(new BlockIndex(slot.x,
slot.y, slot.z));
return slot;
} else {
return slot;
}
} else {
// Even slots that don't need to be build may need

View file

@ -131,7 +131,7 @@ public class BptBuilderTemplate extends BptBuilderBase {
return null;
}
public BuildingSlotBlock internalGetNextBlock(World world, TileAbstractBuilder builder) {
private BuildingSlotBlock internalGetNextBlock(World world, TileAbstractBuilder builder) {
BuildingSlotBlock result = null;
IInvSlot firstSlotToConsume = null;
@ -171,7 +171,10 @@ public class BptBuilderTemplate extends BptBuilderBase {
iterator.remove();
clearedLocations.add(new BlockIndex(slot.x, slot.y, slot.z));
} else {
if (setupForDestroy(builder, context, slot)) {
if (canDestroy(builder, context, slot)) {
consumeEnergyToDestroy(builder, slot);
createDestroyItems(slot);
result = slot;
iterator.remove();
clearedLocations.add(new BlockIndex(slot.x, slot.y, slot.z));

View file

@ -128,10 +128,12 @@ public class BuildingSlotBlock extends BuildingSlot {
NBTTagList nbtStacks = new NBTTagList ();
for (ItemStack stack : stackConsumed) {
NBTTagCompound nbtStack = new NBTTagCompound();
stack.writeToNBT(nbtStack);
nbtStacks.appendTag(nbtStack);
if (stackConsumed != null) {
for (ItemStack stack : stackConsumed) {
NBTTagCompound nbtStack = new NBTTagCompound();
stack.writeToNBT(nbtStack);
nbtStacks.appendTag(nbtStack);
}
}
nbt.setTag("stackConsumed", nbtStacks);

View file

@ -29,6 +29,8 @@ public class AIRobotGotoBlock extends AIRobotGoto {
private LinkedList<BlockIndex> path;
private double prevDistance = Double.MAX_VALUE;
private float finalX, finalY, finalZ;
private double maxDistance = 0;
private BlockIndex lastBlockInPath;
public AIRobotGotoBlock(EntityRobotBase iRobot) {
super(iRobot);
@ -41,6 +43,12 @@ public class AIRobotGotoBlock extends AIRobotGoto {
finalZ = z;
}
public AIRobotGotoBlock(EntityRobotBase robot, int x, int y, int z, double iMaxDistance) {
this(robot, x, y, z);
maxDistance = iMaxDistance;
}
public AIRobotGotoBlock(EntityRobotBase robot, LinkedList<BlockIndex> iPath) {
super(robot);
path = iPath;
@ -60,7 +68,7 @@ public class AIRobotGotoBlock extends AIRobotGoto {
if (path == null && pathSearch == null) {
pathSearch = new PathFinding(robot.worldObj, new BlockIndex((int) Math.floor(robot.posX),
(int) Math.floor(robot.posY), (int) Math.floor(robot.posZ)), new BlockIndex(
(int) Math.floor(finalX), (int) Math.floor(finalY), (int) Math.floor(finalZ)));
(int) Math.floor(finalX), (int) Math.floor(finalY), (int) Math.floor(finalZ)), maxDistance);
pathSearchJob = new PathFindingJob(pathSearch, 100);
pathSearchJob.start();
@ -79,6 +87,7 @@ public class AIRobotGotoBlock extends AIRobotGoto {
} else {
if (pathSearchJob.isDone()) {
path = pathSearch.getResult();
lastBlockInPath = path.getLast();
if (path.size() == 0) {
unreachable = true;
@ -94,9 +103,12 @@ public class AIRobotGotoBlock extends AIRobotGoto {
robot.motionX = 0;
robot.motionY = 0;
robot.motionZ = 0;
robot.posX = finalX + 0.5F;
robot.posY = finalY + 0.5F;
robot.posZ = finalZ + 0.5F;
if (lastBlockInPath != null) {
robot.posX = lastBlockInPath.x + 0.5F;
robot.posY = lastBlockInPath.y + 0.5F;
robot.posZ = lastBlockInPath.z + 0.5F;
}
terminate();
}
@ -127,6 +139,7 @@ public class AIRobotGotoBlock extends AIRobotGoto {
nbt.setFloat("finalX", finalX);
nbt.setFloat("finalY", finalY);
nbt.setFloat("finalZ", finalZ);
nbt.setDouble("maxDistance", maxDistance);
if (path != null) {
NBTTagList pathList = new NBTTagList();
@ -148,6 +161,7 @@ public class AIRobotGotoBlock extends AIRobotGoto {
finalX = nbt.getFloat("finalX");
finalY = nbt.getFloat("finalY");
finalZ = nbt.getFloat("finalZ");
maxDistance = nbt.getDouble("maxDistance");
if (nbt.hasKey("path")) {
NBTTagList pathList = nbt.getTagList("path", Constants.NBT.TAG_COMPOUND);

View file

@ -11,11 +11,13 @@ package buildcraft.core.robots.boards;
import java.util.LinkedList;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import buildcraft.api.boards.RedstoneBoardRobot;
import buildcraft.api.boards.RedstoneBoardRobotNBT;
import buildcraft.api.robots.AIRobot;
import buildcraft.api.robots.EntityRobotBase;
import buildcraft.builders.BuildingItem;
import buildcraft.builders.TileConstructionMarker;
import buildcraft.core.blueprints.BuildingSlot;
import buildcraft.core.inventory.filters.ArrayStackFilter;
@ -29,6 +31,7 @@ public class BoardRobotBuilder extends RedstoneBoardRobot {
private TileConstructionMarker markerToBuild;
private BuildingSlot currentBuildingSlot;
private LinkedList<ItemStack> requirementsToLookFor;
private int launchingDelay = 0;
public BoardRobotBuilder(EntityRobotBase iRobot) {
super(iRobot);
@ -41,6 +44,11 @@ public class BoardRobotBuilder extends RedstoneBoardRobot {
@Override
public void update() {
if (launchingDelay > 0) {
launchingDelay--;
return;
}
if (markerToBuild == null) {
double minDistance = Double.MAX_VALUE;
@ -91,13 +99,13 @@ public class BoardRobotBuilder extends RedstoneBoardRobot {
}
if (currentBuildingSlot != null && requirementsToLookFor != null && requirementsToLookFor.size() == 0) {
// TODO: It's probably OK to get at least X units away from
// destination. something to handle at the path-finding level (e.g.
// end computation) to be brought up to here as a parameter.
startDelegateAI(new AIRobotGotoBlock(robot,
(int) currentBuildingSlot.getDestination().x,
(int) currentBuildingSlot.getDestination().y,
(int) currentBuildingSlot.getDestination().z));
(int) currentBuildingSlot.getDestination().z,
8));
// TODO: take into account cases where the robot can't reach the
// destination - go to work on another block
}
}
@ -115,15 +123,35 @@ public class BoardRobotBuilder extends RedstoneBoardRobot {
// TODO: check that we get the proper items in
requirementsToLookFor.removeFirst();
} else if (ai instanceof AIRobotGotoBlock) {
if (markerToBuild == null || markerToBuild.bluePrintBuilder == null) {
// defensive code, in case of a wrong load from NBT
return;
}
// TODO: we want to update the
// builder state (remove slot from list, add to post processing,
// etc);
// TODO: We need to add destroy animation in the renderer.
launchingDelay = currentBuildingSlot.getStacksToDisplay().size() * BuildingItem.ITEMS_SPACE;
markerToBuild.bluePrintBuilder.buildSlot
(robot.worldObj, markerToBuild, currentBuildingSlot,
robot.posX, robot.posY, robot.posZ);
robot.posX + 0.125F, robot.posY + 0.125F, robot.posZ + 0.125F);
currentBuildingSlot = null;
requirementsToLookFor = null;
}
}
@Override
public void writeSelfToNBT(NBTTagCompound nbt) {
super.writeSelfToNBT(nbt);
nbt.setInteger("launchingDelay", launchingDelay);
}
@Override
public void loadSelfFromNBT(NBTTagCompound nbt) {
super.loadSelfFromNBT(nbt);
launchingDelay = nbt.getInteger("launchingDelay");
}
}

View file

@ -38,6 +38,7 @@ public class PathFinding {
private float sqrMaxDistance = -1;
private IBox box;
private BlockIndex boxCenter;
private double maxDistanceToEnd = 0;
private HashMap<BlockIndex, Node> openList = new HashMap<BlockIndex, PathFinding.Node>();
private HashMap<BlockIndex, Node> closedList = new HashMap<BlockIndex, PathFinding.Node>();
@ -63,6 +64,12 @@ public class PathFinding {
nextIteration = startNode;
}
public PathFinding(World iWorld, BlockIndex iStart, BlockIndex iEnd, double iMaxDistanceToEnd) {
this(iWorld, iStart, iEnd);
maxDistanceToEnd = iMaxDistanceToEnd;
}
public PathFinding(World iWorld, BlockIndex iStart, IBlockFilter iPathFound, float iMaxDistance, IBox iBox) {
world = iWorld;
start = iStart;
@ -228,7 +235,12 @@ public class PathFinding {
} else if (pathFound != null) {
return pathFound.matches(world, x, y, z);
} else {
return end.x == x && end.y == y && end.z == z;
if (maxDistanceToEnd == 0) {
return end.x == x && end.y == y && end.z == z;
} else {
return BuildCraftAPI.isSoftBlock(world, x, y, z)
&& distance(new BlockIndex(x, y, z), end) <= maxDistanceToEnd;
}
}
}