two weeks of agony are finally paying off

This commit is contained in:
Bob 2023-09-30 21:05:46 +02:00
parent abb96d8f4b
commit 743b7a1576
6 changed files with 283 additions and 127 deletions

View File

@ -21,6 +21,7 @@ public class EntityRequestDrone extends EntityDroneBase {
public ItemStack heldItem;
public List program = new ArrayList();
int nextActionTimer = 0;
public static enum DroneProgram {
UNLOAD, DOCK
@ -37,6 +38,12 @@ public class EntityRequestDrone extends EntityDroneBase {
if(!worldObj.isRemote) {
if(Vec3.createVectorHelper(motionX, motionY, motionZ).lengthVector() < 0.01) {
if(nextActionTimer > 0) {
nextActionTimer--;
} else {
nextActionTimer = 5;
if(program.isEmpty()) {
this.setDead(); //self-destruct if no further operations are pending
this.entityDropItem(new ItemStack(ModItems.drone, 1, EnumDroneType.REQUEST.ordinal()), 1F);
@ -44,11 +51,13 @@ public class EntityRequestDrone extends EntityDroneBase {
}
Object next = program.get(0);
System.out.println("next action: " + next);
program.remove(0);
if(next instanceof BlockPos) {
BlockPos pos = (BlockPos) next;
this.setTarget(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5);
System.out.println("targetting");
} else if(next instanceof AStack && heldItem == null) {
AStack aStack = (AStack) next;
@ -69,6 +78,7 @@ public class EntityRequestDrone extends EntityDroneBase {
}
}
}
System.out.println("loading");
} 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));
@ -100,6 +110,7 @@ public class EntityRequestDrone extends EntityDroneBase {
requester.markDirty();
}
System.out.println("unloading");
} else if(next == DroneProgram.DOCK) {
TileEntity tile = worldObj.getTileEntity((int) Math.floor(posX), (int) Math.floor(posY - 1), (int) Math.floor(posZ));
@ -110,6 +121,7 @@ public class EntityRequestDrone extends EntityDroneBase {
if(dock.slots[i] == null) {
this.setDead();
dock.slots[i] = new ItemStack(ModItems.drone, 1, EnumDroneType.REQUEST.ordinal());
break;
}
}
}
@ -118,10 +130,17 @@ public class EntityRequestDrone extends EntityDroneBase {
this.setDead();
this.entityDropItem(new ItemStack(ModItems.drone, 1, EnumDroneType.REQUEST.ordinal()), 1F);
}
System.out.println("docking");
}
}
}
}
}
@Override
public double getSpeed() {
return 0.5D;
}
@Override
protected void readEntityFromNBT(NBTTagCompound nbt) {

View File

@ -2,7 +2,7 @@ package com.hbm.render.entity.item;
import org.lwjgl.opengl.GL11;
import com.hbm.entity.item.EntityDeliveryDrone;
import com.hbm.entity.item.EntityDroneBase;
import com.hbm.entity.item.EntityRequestDrone;
import com.hbm.main.ResourceManager;
@ -29,7 +29,7 @@ public class RenderDeliveryDrone extends Render {
bindTexture(ResourceManager.delivery_drone_tex);
ResourceManager.delivery_drone.renderPart("Drone");
EntityDeliveryDrone drone = (EntityDeliveryDrone) entity;
EntityDroneBase drone = (EntityDroneBase) entity;
int style = drone.getAppearance();
if(style == 1) ResourceManager.delivery_drone.renderPart("Crate");

View File

@ -1,13 +1,12 @@
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;
import java.util.Set;
import com.hbm.inventory.RecipesCommon.AStack;
import com.hbm.util.HashedSet;
import com.hbm.util.fauxpointtwelve.BlockPos;
import net.minecraft.item.ItemStack;
@ -17,7 +16,7 @@ import net.minecraft.world.World;
public class RequestNetwork {
private static int timer = 0;
public static HashMap<World, HashMap<ChunkCoordIntPair, Set<PathNode>>> activeWaypoints = new HashMap();
public static HashMap<World, HashMap<ChunkCoordIntPair, HashedSet<PathNode>>> activeWaypoints = new HashMap();
public static final int maxAge = 2_000;
public static void updateEntries() {
@ -33,13 +32,13 @@ public class RequestNetwork {
// iterate over each dim
while(worldIt.hasNext()) {
Entry<World, HashMap<ChunkCoordIntPair, Set<PathNode>>> worldEntry = (Entry) worldIt.next();
Entry<World, HashMap<ChunkCoordIntPair, HashedSet<PathNode>>> worldEntry = (Entry) worldIt.next();
Iterator chunkIt = worldEntry.getValue().entrySet().iterator();
// iterate over each chunk
while(chunkIt.hasNext()) {
Entry<ChunkCoordIntPair, Set<PathNode>> chunkEntry = (Entry) chunkIt.next();
Entry<ChunkCoordIntPair, HashedSet<PathNode>> chunkEntry = (Entry) chunkIt.next();
Iterator<PathNode> pathIt = chunkEntry.getValue().iterator();
// iterate over each path node
@ -71,10 +70,10 @@ public class RequestNetwork {
public static class PathNode {
public BlockPos pos;
public long lease;
public Set<PathNode> reachableNodes = new HashSet();
public PathNode(BlockPos pos, Set<PathNode> reachableNodes) {
public HashedSet<PathNode> reachableNodes = new HashedSet();
public PathNode(BlockPos pos, HashedSet<PathNode> reachableNodes) {
this.pos = pos;
this.reachableNodes = new HashSet(reachableNodes);
this.reachableNodes = new HashedSet(reachableNodes);
this.lease = System.currentTimeMillis();
}
@Override public int hashCode() { return pos.hashCode(); }
@ -84,7 +83,7 @@ public class RequestNetwork {
/** Node created by providers, lists available items */
public static class OfferNode extends PathNode {
public List<ItemStack> offer;
public OfferNode(BlockPos pos, Set<PathNode> reachableNodes, List<ItemStack> offer) {
public OfferNode(BlockPos pos, HashedSet<PathNode> reachableNodes, List<ItemStack> offer) {
super(pos, reachableNodes);
this.offer = offer;
}
@ -93,7 +92,7 @@ public class RequestNetwork {
/** Node created by requesters, lists requested AStacks */
public static class RequestNode extends PathNode {
public List<AStack> request;
public RequestNode(BlockPos pos, Set<PathNode> reachableNodes, List<AStack> request) {
public RequestNode(BlockPos pos, HashedSet<PathNode> reachableNodes, List<AStack> request) {
super(pos, reachableNodes);
this.request = request;
}

View File

@ -3,7 +3,6 @@ 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;
@ -16,6 +15,7 @@ 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.HashedSet;
import com.hbm.util.fauxpointtwelve.BlockPos;
import cpw.mods.fml.relauncher.Side;
@ -46,7 +46,7 @@ public class TileEntityDroneDock extends TileEntityRequestNetworkContainer imple
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);
HashedSet<PathNode> localNodes = this.getAllLocalNodes(worldObj, xCoord, zCoord, 5);
List<RequestNode> requests = new ArrayList();
List<OfferNode> offers = new ArrayList();
@ -72,14 +72,14 @@ public class TileEntityDroneDock extends TileEntityRequestNetworkContainer imple
if(firstRequest != null) {
PathNode own = createNode(new BlockPos(xCoord, yCoord + 1, zCoord));
PathNode own = localNodes.getMap().get(new BlockPos(xCoord, yCoord + 1, zCoord).hashCode());
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
if(tryEmbark(own, firstRequest, offer, request, localNodes)) break attempt; // if the drone can be pathed and spawned, stop doing more attempts
break outer; // if not, simply continue iterating over offer nodes
}
}
@ -89,13 +89,13 @@ public class TileEntityDroneDock extends TileEntityRequestNetworkContainer imple
}
}
public boolean tryEmbark(PathNode dock, RequestNode request, OfferNode offer, AStack item) {
public boolean tryEmbark(PathNode dock, RequestNode request, OfferNode offer, AStack item, HashedSet localNodes) {
List<PathNode> dockToOffer = generatePath(dock, offer);
List<PathNode> dockToOffer = generatePath(dock, offer, localNodes);
if(dockToOffer == null) return false;
List<PathNode> offerToRequest = generatePath(offer, request);
List<PathNode> offerToRequest = generatePath(offer, request, localNodes);
if(offerToRequest == null) return false;
List<PathNode> requestToDock = generatePath(request, dock);
List<PathNode> requestToDock = generatePath(request, dock, localNodes);
if(requestToDock == null) return false;
@ -111,20 +111,22 @@ public class TileEntityDroneDock extends TileEntityRequestNetworkContainer imple
drone.setPosition(xCoord + 0.5, yCoord + 1, zCoord + 0.5);
// write programming
for(PathNode node : dockToOffer) drone.program.add(node);
drone.program.add(offer);
for(PathNode node : dockToOffer) drone.program.add(node.pos);
drone.program.add(offer.pos);
drone.program.add(item);
for(PathNode node : offerToRequest) drone.program.add(node);
drone.program.add(request);
for(PathNode node : offerToRequest) drone.program.add(node.pos);
drone.program.add(request.pos);
drone.program.add(DroneProgram.UNLOAD);
for(PathNode node : requestToDock) drone.program.add(node);
drone.program.add(dock);
for(PathNode node : requestToDock) drone.program.add(node.pos);
drone.program.add(dock.pos);
drone.program.add(DroneProgram.DOCK);
worldObj.spawnEntityInWorld(drone);
return true;
}
public List<PathNode> generatePath(PathNode start, PathNode end) {
public List<PathNode> generatePath(PathNode start, PathNode end, HashedSet<PathNode> localNodes) {
List<List<PathNode>> paths = new ArrayList();
List<PathNode> init = new ArrayList();
@ -137,19 +139,24 @@ public class TileEntityDroneDock extends TileEntityRequestNetworkContainer imple
List<List<PathNode>> newPaths = new ArrayList();
for(List<PathNode> oldPath : paths) {
for(PathNode connected : oldPath.get(oldPath.size() - 1).reachableNodes) {
for(PathNode connectedUnsafe : oldPath.get(oldPath.size() - 1).reachableNodes) {
PathNode connectedSafe = localNodes.getMap().get(connectedUnsafe.hashCode()); // lookup to translate potentially outdated nodes into current ones
if(connectedSafe != null) {
List<PathNode> newPath = new ArrayList();
newPath.addAll(oldPath);
if(connected.hashCode() == end.hashCode()) {
if(connectedSafe.hashCode() == end.hashCode()) {
newPath.remove(0); // we only want the in-betweens
return newPath;
}
newPath.add(connected);
newPath.add(connectedSafe);
newPaths.add(newPath);
}
}
}
paths = newPaths;
}

View File

@ -1,13 +1,12 @@
package com.hbm.tileentity.network;
import java.util.HashMap;
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.HashedSet;
import com.hbm.util.ParticleUtil;
import com.hbm.util.fauxpointtwelve.BlockPos;
@ -31,8 +30,8 @@ import net.minecraft.world.World;
*/
public abstract class TileEntityRequestNetwork extends TileEntity {
public Set<PathNode> reachableNodes = new HashSet();
public Set<PathNode> knownNodes = new HashSet();
public HashedSet<PathNode> reachableNodes = new HashedSet();
public HashedSet<PathNode> knownNodes = new HashedSet();
public static final int maxRange = 24;
@Override
@ -48,7 +47,7 @@ public abstract class TileEntityRequestNetwork extends TileEntity {
// remove known nodes that no longer exist
// 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
HashedSet<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();
@ -136,7 +135,7 @@ public abstract class TileEntityRequestNetwork extends TileEntity {
*/
public static void push(World world, PathNode node) {
HashMap<ChunkCoordIntPair, Set<PathNode>> coordMap = RequestNetwork.activeWaypoints.get(world);
HashMap<ChunkCoordIntPair, HashedSet<PathNode>> coordMap = RequestNetwork.activeWaypoints.get(world);
if(coordMap == null) {
coordMap = new HashMap();
@ -144,10 +143,10 @@ public abstract class TileEntityRequestNetwork extends TileEntity {
}
ChunkCoordIntPair chunkPos = new ChunkCoordIntPair(node.pos.getX() >> 4, node.pos.getZ() >> 4);
Set<PathNode> posList = coordMap.get(chunkPos);
HashedSet<PathNode> posList = coordMap.get(chunkPos);
if(posList == null) {
posList = new HashSet();
posList = new HashedSet();
coordMap.put(chunkPos, posList);
}
@ -162,22 +161,22 @@ public abstract class TileEntityRequestNetwork extends TileEntity {
* @param z
* @return
*/
public static Set<PathNode> getAllLocalNodes(World world, int x, int z, int range) {
public static HashedSet<PathNode> getAllLocalNodes(World world, int x, int z, int range) {
Set<PathNode> nodes = new HashSet();
Set<BlockPos> pos = new HashSet();
HashedSet<PathNode> nodes = new HashedSet();
HashedSet<BlockPos> pos = new HashedSet();
x >>= 4;
z >>= 4;
HashMap<ChunkCoordIntPair, Set<PathNode>> coordMap = RequestNetwork.activeWaypoints.get(world);
HashMap<ChunkCoordIntPair, HashedSet<PathNode>> coordMap = RequestNetwork.activeWaypoints.get(world);
if(coordMap == null) return nodes;
for(int i = -range; i <= range; i++) {
for(int j = -range; j <= range; j++) {
Set<PathNode> nodeList = coordMap.get(new ChunkCoordIntPair(x + i, z + j));
HashedSet<PathNode> nodeList = coordMap.get(new ChunkCoordIntPair(x + i, z + j));
if(nodeList != null) for(PathNode node : nodeList) {
if(!pos.contains(node.pos)) {

View File

@ -0,0 +1,132 @@
package com.hbm.util;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;
import org.apache.commons.lang3.NotImplementedException;
/**
* Through whichever mechanism, HashSets allow for multiple instances with the same hash, even though they already has that hash during instantiation
* How is this possible? I don't know and I don't want to know.
*
* This is a crude recreation using a HashMap and, instead of whichever braindead bullshit HashSet does, this HashMap uses the hashCode() as the key and the object as the value.
*
* @author hbm
*
* @param <T>
*/
public class HashedSet<T> implements Set<T> {
HashMap<Integer, T> map = new HashMap();
public static class HashedIterator<T> implements Iterator {
private Iterator<Entry<Integer, T>> iterator;
public HashedIterator(HashedSet<T> set) {
this.iterator = set.map.entrySet().iterator();
}
@Override
public boolean hasNext() {
return this.iterator.hasNext();
}
@Override
public Object next() {
return this.iterator.next().getValue();
}
@Override
public void remove() {
this.iterator.remove();
}
}
public HashedSet() { }
public HashedSet(Set reachableNodes) {
this.addAll(reachableNodes);
}
public HashMap<Integer, T> getMap() {
return this.map;
}
@Override
public boolean add(Object e) {
boolean contains = this.contains(e);
this.map.put(e.hashCode(), (T) e);
return contains;
}
@Override
public boolean addAll(Collection c) {
boolean ret = false;
for(Object o : c) if(add(o)) ret = true;
return ret;
}
@Override
public void clear() {
this.map.clear();
}
@Override
public boolean contains(Object o) {
return this.map.containsKey(o.hashCode());
}
@Override
public boolean containsAll(Collection c) {
for(Object o : c) {
if(!this.contains(o)) return false;
}
return true;
}
@Override
public boolean isEmpty() {
return this.map.isEmpty();
}
@Override
public Iterator iterator() {
return new HashedIterator(this);
}
@Override
public boolean remove(Object o) {
return false;
}
@Override
public boolean removeAll(Collection c) {
return false;
}
@Override
public boolean retainAll(Collection c) {
throw new NotImplementedException("Fuck you");
}
@Override
public int size() {
return this.map.size();
}
@Override
public Object[] toArray() {
throw new NotImplementedException("Fuck you");
}
@Override
public Object[] toArray(Object[] a) {
throw new NotImplementedException("Fuck you");
}
}