stalingrad

This commit is contained in:
Bob 2023-09-30 19:46:09 +02:00
parent ad2174b639
commit abb96d8f4b
9 changed files with 355 additions and 85 deletions

View File

@ -5,14 +5,11 @@ import com.hbm.inventory.FluidStack;
import com.hbm.inventory.fluid.Fluids;
import com.hbm.main.MainRegistry;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.util.Vec3;
import net.minecraft.world.ChunkCoordIntPair;
import net.minecraft.world.World;
import net.minecraftforge.common.ForgeChunkManager;
@ -24,16 +21,11 @@ public class EntityDeliveryDrone extends EntityDroneBase implements IInventory,
protected ItemStack[] slots = new ItemStack[this.getSizeInventory()];
public FluidStack fluid;
public double targetX = -1;
public double targetY = -1;
public double targetZ = -1;
private Ticket loaderTicket;
public boolean isChunkLoading = false;
public EntityDeliveryDrone(World world) {
super(world);
this.setSize(1.5F, 2.0F);
}
@Override
@ -47,39 +39,14 @@ public class EntityDeliveryDrone extends EntityDroneBase implements IInventory,
return this;
}
public void setTarget(double x, double y, double z) {
this.targetX = x;
this.targetY = y;
this.targetZ = z;
}
@Override
public void onUpdate() {
super.onUpdate();
if(!worldObj.isRemote) {
this.motionX = 0;
this.motionY = 0;
this.motionZ = 0;
if(this.targetY != -1) {
Vec3 dist = Vec3.createVectorHelper(targetX - posX, targetY - posY, targetZ - posZ);
double speed = getSpeed();
if(dist.lengthVector() >= speed) {
dist = dist.normalize();
this.motionX = dist.xCoord * speed;
this.motionY = dist.yCoord * speed;
this.motionZ = dist.zCoord * speed;
}
}
loadNeighboringChunks((int)Math.floor(posX / 16D), (int)Math.floor(posZ / 16D));
this.moveEntity(motionX, motionY, motionZ);
}
super.onUpdate();
}
@Override
@ -89,10 +56,7 @@ public class EntityDeliveryDrone extends EntityDroneBase implements IInventory,
@Override
protected void writeEntityToNBT(NBTTagCompound nbt) {
nbt.setDouble("tX", targetX);
nbt.setDouble("tY", targetY);
nbt.setDouble("tZ", targetZ);
super.writeEntityToNBT(nbt);
NBTTagList nbttaglist = new NBTTagList();
@ -112,18 +76,12 @@ public class EntityDeliveryDrone extends EntityDroneBase implements IInventory,
nbt.setInteger("fluidAmount", fluid.fill);
}
nbt.setByte("app", this.dataWatcher.getWatchableObjectByte(10));
nbt.setByte("load", this.dataWatcher.getWatchableObjectByte(11));
}
@Override
protected void readEntityFromNBT(NBTTagCompound nbt) {
if(nbt.hasKey("tY")) {
this.targetX = nbt.getDouble("tX");
this.targetY = nbt.getDouble("tY");
this.targetZ = nbt.getDouble("tZ");
}
super.readEntityFromNBT(nbt);
NBTTagList nbttaglist = nbt.getTagList("Items", 10);
this.slots = new ItemStack[this.getSizeInventory()];
@ -141,21 +99,9 @@ public class EntityDeliveryDrone extends EntityDroneBase implements IInventory,
this.fluid = new FluidStack(Fluids.fromName(nbt.getString("fluidType")), nbt.getInteger("fluidAmount"));
}
this.dataWatcher.updateObject(10, nbt.getByte("app"));
this.dataWatcher.updateObject(11, nbt.getByte("load"));
}
@SideOnly(Side.CLIENT)
public void setPositionAndRotation2(double x, double y, double z, float yaw, float pitch, int theNumberThree) {
this.syncPosX = x;
this.syncPosY = y;
this.syncPosZ = z;
this.turnProgress = theNumberThree;
this.motionX = this.velocityX;
this.motionY = this.velocityY;
this.motionZ = this.velocityZ;
}
@Override
public ItemStack getStackInSlot(int slot) {
return slots[slot];

View File

@ -4,6 +4,8 @@ import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
public abstract class EntityDroneBase extends Entity {
@ -16,8 +18,19 @@ public abstract class EntityDroneBase extends Entity {
@SideOnly(Side.CLIENT) protected double velocityY;
@SideOnly(Side.CLIENT) protected double velocityZ;
public double targetX = -1;
public double targetY = -1;
public double targetZ = -1;
public EntityDroneBase(World world) {
super(world);
this.setSize(1.5F, 2.0F);
}
public void setTarget(double x, double y, double z) {
this.targetX = x;
this.targetY = y;
this.targetZ = z;
}
@Override
@ -81,6 +94,26 @@ public abstract class EntityDroneBase extends Entity {
worldObj.spawnParticle("smoke", posX - 1.125, posY + 0.75, posZ, 0, -0.2, 0);
worldObj.spawnParticle("smoke", posX, posY + 0.75, posZ + 1.125, 0, -0.2, 0);
worldObj.spawnParticle("smoke", posX, posY + 0.75, posZ - 1.125, 0, -0.2, 0);
} else {
this.motionX = 0;
this.motionY = 0;
this.motionZ = 0;
if(this.targetY != -1) {
Vec3 dist = Vec3.createVectorHelper(targetX - posX, targetY - posY, targetZ - posZ);
double speed = getSpeed();
if(dist.lengthVector() >= speed) {
dist = dist.normalize();
this.motionX = dist.xCoord * speed;
this.motionY = dist.yCoord * speed;
this.motionZ = dist.zCoord * speed;
}
}
this.moveEntity(motionX, motionY, motionZ);
}
}
@ -94,4 +127,37 @@ public abstract class EntityDroneBase extends Entity {
this.velocityY = this.motionY = motionY;
this.velocityZ = this.motionZ = motionZ;
}
@SideOnly(Side.CLIENT)
public void setPositionAndRotation2(double x, double y, double z, float yaw, float pitch, int theNumberThree) {
this.syncPosX = x;
this.syncPosY = y;
this.syncPosZ = z;
this.turnProgress = theNumberThree;
this.motionX = this.velocityX;
this.motionY = this.velocityY;
this.motionZ = this.velocityZ;
}
@Override
protected void writeEntityToNBT(NBTTagCompound nbt) {
nbt.setDouble("tX", targetX);
nbt.setDouble("tY", targetY);
nbt.setDouble("tZ", targetZ);
nbt.setByte("app", this.dataWatcher.getWatchableObjectByte(10));
}
@Override
protected void readEntityFromNBT(NBTTagCompound nbt) {
if(nbt.hasKey("tY")) {
this.targetX = nbt.getDouble("tX");
this.targetY = nbt.getDouble("tY");
this.targetZ = nbt.getDouble("tZ");
}
this.dataWatcher.updateObject(10, nbt.getByte("app"));
}
}

View File

@ -1,17 +1,128 @@
package com.hbm.entity.item;
import java.util.ArrayList;
import java.util.List;
import com.hbm.inventory.RecipesCommon.AStack;
import com.hbm.items.ModItems;
import com.hbm.items.tool.ItemDrone.EnumDroneType;
import com.hbm.tileentity.network.TileEntityDroneDock;
import com.hbm.tileentity.network.TileEntityDroneProvider;
import com.hbm.tileentity.network.TileEntityDroneRequester;
import com.hbm.util.fauxpointtwelve.BlockPos;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
public class EntityRequestDrone extends EntityDroneBase {
public ItemStack heldItem;
public List program = new ArrayList();
public static enum DroneProgram {
UNLOAD, DOCK
}
public EntityRequestDrone(World world) {
super(world);
}
@Override
public void onUpdate() {
super.onUpdate();
if(!worldObj.isRemote) {
if(Vec3.createVectorHelper(motionX, motionY, motionZ).lengthVector() < 0.01) {
if(program.isEmpty()) {
this.setDead(); //self-destruct if no further operations are pending
this.entityDropItem(new ItemStack(ModItems.drone, 1, EnumDroneType.REQUEST.ordinal()), 1F);
return;
}
Object next = program.get(0);
program.remove(0);
if(next instanceof BlockPos) {
BlockPos pos = (BlockPos) next;
this.setTarget(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5);
} else if(next instanceof AStack && heldItem == null) {
AStack aStack = (AStack) next;
TileEntity tile = worldObj.getTileEntity((int) Math.floor(posX), (int) Math.floor(posY - 1), (int) Math.floor(posZ));
if(tile instanceof TileEntityDroneProvider) {
TileEntityDroneProvider provider = (TileEntityDroneProvider) tile;
for(int i = 0; i < provider.slots.length; i++) {
ItemStack stack = provider.slots[i];
if(stack != null && aStack.matchesRecipe(stack, true)) {
this.heldItem = stack.copy();
this.setAppearance(1);
provider.slots[i] = null;
provider.markDirty();
break;
}
}
}
} else if(next == DroneProgram.UNLOAD && this.heldItem != null) {
TileEntity tile = worldObj.getTileEntity((int) Math.floor(posX), (int) Math.floor(posY - 1), (int) Math.floor(posZ));
if(tile instanceof TileEntityDroneRequester) {
TileEntityDroneRequester requester = (TileEntityDroneRequester) tile;
for(int i = 9; i < 18; i++) {
ItemStack stack = requester.slots[i];
if(stack != null && stack.getItem() == heldItem.getItem() && stack.getItemDamage() == heldItem.getItemDamage()) {
int toTransfer = Math.min(stack.getMaxStackSize() - stack.stackSize, heldItem.stackSize);
requester.slots[i].stackSize += toTransfer;
this.heldItem.stackSize -= toTransfer;
}
}
if(this.heldItem.stackSize <= 0) this.heldItem = null;
if(this.heldItem != null) for(int i = 9; i < 18; i++) {
if(requester.slots[i] == null) {
requester.slots[i] = this.heldItem.copy();
this.heldItem = null;
break;
}
}
if(this.heldItem == null) {
this.setAppearance(0);
}
requester.markDirty();
}
} else if(next == DroneProgram.DOCK) {
TileEntity tile = worldObj.getTileEntity((int) Math.floor(posX), (int) Math.floor(posY - 1), (int) Math.floor(posZ));
if(tile instanceof TileEntityDroneDock) {
TileEntityDroneDock dock = (TileEntityDroneDock) tile;
for(int i = 0; i < dock.slots.length; i++) {
if(dock.slots[i] == null) {
this.setDead();
dock.slots[i] = new ItemStack(ModItems.drone, 1, EnumDroneType.REQUEST.ordinal());
}
}
}
if(!this.isDead) {
this.setDead();
this.entityDropItem(new ItemStack(ModItems.drone, 1, EnumDroneType.REQUEST.ordinal()), 1F);
}
}
}
}
}
@Override
protected void readEntityFromNBT(NBTTagCompound nbt) {

View File

@ -1,6 +1,7 @@
package com.hbm.tileentity.network;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
@ -47,6 +48,7 @@ public class RequestNetwork {
// if the lease timestamp is too far back, time out the node
if(node.lease < System.currentTimeMillis() - maxAge) {
node.reachableNodes.clear(); // just to be sure there's no cyclical references happening creating memory leaks
pathIt.remove();
}
}
@ -69,8 +71,10 @@ public class RequestNetwork {
public static class PathNode {
public BlockPos pos;
public long lease;
public PathNode(BlockPos pos) {
public Set<PathNode> reachableNodes = new HashSet();
public PathNode(BlockPos pos, Set<PathNode> reachableNodes) {
this.pos = pos;
this.reachableNodes = new HashSet(reachableNodes);
this.lease = System.currentTimeMillis();
}
@Override public int hashCode() { return pos.hashCode(); }
@ -80,8 +84,8 @@ public class RequestNetwork {
/** Node created by providers, lists available items */
public static class OfferNode extends PathNode {
public List<ItemStack> offer;
public OfferNode(BlockPos pos, List<ItemStack> offer) {
super(pos);
public OfferNode(BlockPos pos, Set<PathNode> reachableNodes, List<ItemStack> offer) {
super(pos, reachableNodes);
this.offer = offer;
}
}
@ -89,8 +93,8 @@ public class RequestNetwork {
/** Node created by requesters, lists requested AStacks */
public static class RequestNode extends PathNode {
public List<AStack> request;
public RequestNode(BlockPos pos, List<AStack> request) {
super(pos);
public RequestNode(BlockPos pos, Set<PathNode> reachableNodes, List<AStack> request) {
super(pos, reachableNodes);
this.request = request;
}
}

View File

@ -1,9 +1,21 @@
package com.hbm.tileentity.network;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import com.hbm.entity.item.EntityRequestDrone;
import com.hbm.entity.item.EntityRequestDrone.DroneProgram;
import com.hbm.inventory.RecipesCommon.AStack;
import com.hbm.inventory.container.ContainerDroneDock;
import com.hbm.inventory.gui.GUIDroneDock;
import com.hbm.items.ModItems;
import com.hbm.items.tool.ItemDrone.EnumDroneType;
import com.hbm.tileentity.IGUIProvider;
import com.hbm.tileentity.network.RequestNetwork.OfferNode;
import com.hbm.tileentity.network.RequestNetwork.PathNode;
import com.hbm.tileentity.network.RequestNetwork.RequestNode;
import com.hbm.util.fauxpointtwelve.BlockPos;
import cpw.mods.fml.relauncher.Side;
@ -11,10 +23,13 @@ import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.Container;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
public class TileEntityDroneDock extends TileEntityRequestNetworkContainer implements IGUIProvider {
public static final int pathingDepth = 5;
public TileEntityDroneDock() {
super(9);
}
@ -27,6 +42,129 @@ public class TileEntityDroneDock extends TileEntityRequestNetworkContainer imple
@Override
public void updateEntity() {
super.updateEntity();
if(!worldObj.isRemote && worldObj.getTotalWorldTime() % 100 == 0 && this.hasDrone()) {
// grab all nodes in a 5 chunk radius
Set<PathNode> localNodes = this.getAllLocalNodes(worldObj, xCoord, zCoord, 5);
List<RequestNode> requests = new ArrayList();
List<OfferNode> offers = new ArrayList();
for(PathNode local : localNodes) {
if(local instanceof RequestNode) requests.add((RequestNode) local);
if(local instanceof OfferNode) offers.add((OfferNode) local);
}
attempt: for(int i = 0; i < 5; i++) {
// randomize!
Collections.shuffle(requests);
Collections.shuffle(offers);
RequestNode firstRequest = null;
// simply pick the first request node that has unfulfilled requests
for(RequestNode request : requests) {
if(!request.request.isEmpty()) {
firstRequest = request;
break;
}
}
if(firstRequest != null) {
PathNode own = createNode(new BlockPos(xCoord, yCoord + 1, zCoord));
AStack request = firstRequest.request.get(worldObj.rand.nextInt(firstRequest.request.size()));
outer: for(OfferNode offer : offers) {
for(ItemStack stack : offer.offer) {
if(stack != null && request.matchesRecipe(stack, true)) {
if(tryEmbark(own, firstRequest, offer, request)) break attempt; // if the drone can be pathed and spawned, stop doing more attempts
break outer; // if not, simply continue iterating over offer nodes
}
}
}
}
}
}
}
public boolean tryEmbark(PathNode dock, RequestNode request, OfferNode offer, AStack item) {
List<PathNode> dockToOffer = generatePath(dock, offer);
if(dockToOffer == null) return false;
List<PathNode> offerToRequest = generatePath(offer, request);
if(offerToRequest == null) return false;
List<PathNode> requestToDock = generatePath(request, dock);
if(requestToDock == null) return false;
for(int i = 0; i < this.slots.length; i++) {
ItemStack stack = slots[i];
if(stack != null && stack.getItem() == ModItems.drone && stack.getItemDamage() == EnumDroneType.REQUEST.ordinal()) {
this.decrStackSize(i, 1);
break;
}
}
EntityRequestDrone drone = new EntityRequestDrone(worldObj);
drone.setPosition(xCoord + 0.5, yCoord + 1, zCoord + 0.5);
// write programming
for(PathNode node : dockToOffer) drone.program.add(node);
drone.program.add(offer);
drone.program.add(item);
for(PathNode node : offerToRequest) drone.program.add(node);
drone.program.add(request);
drone.program.add(DroneProgram.UNLOAD);
for(PathNode node : requestToDock) drone.program.add(node);
drone.program.add(dock);
drone.program.add(DroneProgram.DOCK);
return true;
}
public List<PathNode> generatePath(PathNode start, PathNode end) {
List<List<PathNode>> paths = new ArrayList();
List<PathNode> init = new ArrayList();
init.add(start);
paths.add(init);
// breadth-first search
for(int i = 0; i < pathingDepth; i++) {
List<List<PathNode>> newPaths = new ArrayList();
for(List<PathNode> oldPath : paths) {
for(PathNode connected : oldPath.get(oldPath.size() - 1).reachableNodes) {
List<PathNode> newPath = new ArrayList();
newPath.addAll(oldPath);
if(connected.hashCode() == end.hashCode()) {
newPath.remove(0); // we only want the in-betweens
return newPath;
}
newPath.add(connected);
newPaths.add(newPath);
}
}
paths = newPaths;
}
return null;
}
public boolean hasDrone() {
for(int i = 0; i < this.slots.length; i++) {
ItemStack stack = slots[i];
if(stack != null && stack.getItem() == ModItems.drone && stack.getItemDamage() == EnumDroneType.REQUEST.ordinal()) return true;
}
return false;
}
@Override
@ -42,6 +180,6 @@ public class TileEntityDroneDock extends TileEntityRequestNetworkContainer imple
@Override
public PathNode createNode(BlockPos pos) {
return new PathNode(pos);
return new PathNode(pos, this.reachableNodes);
}
}

View File

@ -59,6 +59,6 @@ public class TileEntityDroneProvider extends TileEntityRequestNetworkContainer i
public PathNode createNode(BlockPos pos) {
List<ItemStack> offer = new ArrayList();
for(ItemStack stack : slots) if(stack != null) offer.add(stack.copy());
return new OfferNode(pos, offer);
return new OfferNode(pos, this.reachableNodes, offer);
}
}

View File

@ -56,19 +56,6 @@ public class TileEntityDroneRequester extends TileEntityRequestNetworkContainer
this.matcher.readFromNBT(nbt);
}
public boolean matchesFilter(ItemStack stack) {
for(int i = 0; i < 9; i++) {
ItemStack filter = slots[i];
if(filter != null && this.matcher.isValidForFilter(filter, i, stack)) {
return true;
}
}
return false;
}
public void nextMode(int i) {
this.matcher.nextMode(worldObj, slots[i], i);
}
@ -104,6 +91,7 @@ public class TileEntityDroneRequester extends TileEntityRequestNetworkContainer
List<AStack> request = new ArrayList();
for(int i = 0; i < 9; i++) {
ItemStack filter = slots[i];
ItemStack stock = slots[i + 9];
if(filter == null) continue;
String mode = this.matcher.modes[i];
AStack aStack = null;
@ -112,12 +100,14 @@ public class TileEntityDroneRequester extends TileEntityRequestNetworkContainer
aStack = new ComparableStack(filter).makeSingular();
} else if(ModulePatternMatcher.MODE_WILDCARD.equals(mode)) {
aStack = new ComparableStack(filter.getItem(), 1, OreDictionary.WILDCARD_VALUE);
} else {
} else if(mode != null) {
aStack = new OreDictStack(mode);
}
request.add(aStack);
if(aStack == null) continue;
if(stock == null || !this.matcher.isValidForFilter(filter, i, stock)) request.add(aStack);
}
return new RequestNode(pos, request);
return new RequestNode(pos, this.reachableNodes, request);
}
}

View File

@ -38,6 +38,6 @@ public class TileEntityDroneWaypointRequest extends TileEntityRequestNetwork {
@Override
public PathNode createNode(BlockPos pos) {
return new PathNode(pos);
return new PathNode(pos, this.reachableNodes);
}
}

View File

@ -5,10 +5,14 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import com.hbm.packet.AuxParticlePacketNT;
import com.hbm.packet.PacketDispatcher;
import com.hbm.tileentity.network.RequestNetwork.PathNode;
import com.hbm.util.ParticleUtil;
import com.hbm.util.fauxpointtwelve.BlockPos;
import cpw.mods.fml.common.network.NetworkRegistry.TargetPoint;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.Vec3;
@ -45,6 +49,7 @@ public abstract class TileEntityRequestNetwork extends TileEntity {
// since we can assume a sane number of nodes to exist at any given time, we can run this check in full every second
Iterator<PathNode> it = knownNodes.iterator();
Set<PathNode> localNodes = this.getAllLocalNodes(worldObj, xCoord, zCoord, 2); // this bit may spiral into multiple nested hashtable lookups but it's limited to only a few chunks so it shouldn't be an issue
localNodes.remove(pos);
while(it.hasNext()) {
PathNode node = it.next();
if(!localNodes.contains(node)) {
@ -61,6 +66,13 @@ public abstract class TileEntityRequestNetwork extends TileEntity {
reachableNodes.contains(known) ? 0x00ff00 : 0xff0000);
}
NBTTagCompound data = new NBTTagCompound();
data.setString("type", "debug");
data.setInteger("color", 0x0000ff);
data.setFloat("scale", 1.5F);
data.setString("text", knownNodes.size() + " / " + reachableNodes.size() + " / " + localNodes.size());
PacketDispatcher.wrapper.sendToAllAround(new AuxParticlePacketNT(data, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5), new TargetPoint(this.worldObj.provider.dimensionId, xCoord, yCoord, zCoord, 50));
//both following checks run the `hasPath` function which is costly, so it only runs one op at a time
//rescan known nodes
@ -153,6 +165,7 @@ public abstract class TileEntityRequestNetwork extends TileEntity {
public static Set<PathNode> getAllLocalNodes(World world, int x, int z, int range) {
Set<PathNode> nodes = new HashSet();
Set<BlockPos> pos = new HashSet();
x >>= 4;
z >>= 4;
@ -167,12 +180,14 @@ public abstract class TileEntityRequestNetwork extends TileEntity {
Set<PathNode> nodeList = coordMap.get(new ChunkCoordIntPair(x + i, z + j));
if(nodeList != null) for(PathNode node : nodeList) {
nodes.add(node);
if(!pos.contains(node.pos)) {
nodes.add(node);
//pos.add(node.pos);
}
}
}
}
return nodes;
}
}