use of am2.api.power.IPowerNode in project ArsMagica2 by Mithion.
the class PowerNodeRegistry method getAllNearbyNodes.
/**
* Returns all power nodes within POWER_SEARCH_RADIUS
*
* @param location The center point to search from
* @param power The power type that the provider needs to supply or accept to be considered valid
* @return An array of IPowerNodes
*/
public IPowerNode[] getAllNearbyNodes(World world, AMVector3 location, PowerTypes power) {
//get the list of chunks we'll need to search in
ChunkCoordIntPair[] search = getSearchChunks(location);
//build the list of nodes from that chunk
HashMap<AMVector3, PowerNodeEntry> nodesToSearch = new HashMap<AMVector3, PowerNodeEntry>();
for (ChunkCoordIntPair pair : search) {
HashMap<AMVector3, PowerNodeEntry> nodesInChunk = powerNodes.get(pair);
if (nodesInChunk != null) {
//Add only vectors that are less than or equal to POWER_SEARCH_RADIUS_SQ away
for (AMVector3 vector : nodesInChunk.keySet()) {
if (location.distanceSqTo(vector) <= POWER_SEARCH_RADIUS_SQ && !vector.equals(location)) {
nodesToSearch.put(vector, nodesInChunk.get(vector));
}
}
}
}
//spin through and create our list of providers
ArrayList<IPowerNode> nodes = new ArrayList<IPowerNode>();
int deadNodesRemoved = 0;
for (AMVector3 vector : nodesToSearch.keySet()) {
if (!world.checkChunksExist((int) vector.x, (int) vector.y, (int) vector.z, (int) vector.x, (int) vector.y, (int) vector.z)) {
continue;
}
Chunk chunk = world.getChunkFromBlockCoords((int) vector.x, (int) vector.z);
if (!chunk.isChunkLoaded)
continue;
TileEntity te = world.getTileEntity((int) vector.x, (int) vector.y, (int) vector.z);
if (te == null || !(te instanceof IPowerNode)) {
//opportune time to remove dead power nodes
removePowerNode(chunk.getChunkCoordIntPair(), vector);
deadNodesRemoved++;
continue;
}
IPowerNode node = (IPowerNode) te;
nodes.add(node);
}
if (deadNodesRemoved > 0)
LogHelper.trace("Removed %d dead power nodes", deadNodesRemoved);
IPowerNode[] nodeArray = nodes.toArray(new IPowerNode[nodes.size()]);
LogHelper.trace("Located %d nearby power providers", nodeArray.length);
return nodeArray;
}
use of am2.api.power.IPowerNode in project ArsMagica2 by Mithion.
the class PowerNodeRegistry method tryPairNodes.
/**
* Attempts to pair the source and destination nodes by either a direct link or by going through conduits.
*
* @param powerSource The power source
* @param destination The destination point
* @return A localized message to return to the entity attempting to pair the nodes, either of success or why it failed.
*/
public String tryPairNodes(IPowerNode powerSource, IPowerNode destination) {
if (powerSource == destination) {
return StatCollector.translateToLocal("am2.tooltip.nodePairToSelf");
}
//Can the power source provide any of the valid power types for the destination?
ArrayList<PowerTypes> typesProvided = new ArrayList<PowerTypes>();
for (PowerTypes type : destination.getValidPowerTypes()) {
if (powerSource.canProvidePower(type)) {
typesProvided.add(type);
}
}
if (typesProvided.size() == 0) {
//no valid power types can be provided
return StatCollector.translateToLocal("am2.tooltip.noSupportedPowertypes");
}
//set up vectors and calculate distance for pathing purposes
AMVector3 sourceLocation = new AMVector3((TileEntity) powerSource);
AMVector3 destLocation = new AMVector3((TileEntity) destination);
double rawDist = sourceLocation.distanceSqTo(destLocation);
if (rawDist > MAX_POWER_SEARCH_RADIUS) {
return StatCollector.translateToLocal("am2.tooltip.nodesTooFar");
}
//construct a list of all valid power types common between the source and destination
int successes = 0;
for (PowerTypes type : typesProvided) {
LinkedList<AMVector3> powerPath = new LinkedList<AMVector3>();
PowerNodePathfinder pathfinder = new PowerNodePathfinder(((TileEntity) powerSource).getWorldObj(), sourceLocation, destLocation, type);
List<AMVector3> path = pathfinder.compute(sourceLocation);
if (path == null)
continue;
for (AMVector3 vec : path) {
powerPath.addFirst(vec);
}
successes++;
getPowerNodeData(destination).registerNodePath(type, powerPath);
}
//are the nodes too far apart?
if (successes == 0) {
return StatCollector.translateToLocal("am2.tooltip.noPathFound");
}
if (successes == typesProvided.size())
return StatCollector.translateToLocal("am2.tooltip.success");
return StatCollector.translateToLocal("am2.tooltip.partialSuccess");
}
use of am2.api.power.IPowerNode in project ArsMagica2 by Mithion.
the class PowerNodeRegistry method registerPowerNodeInternal.
PowerNodeEntry registerPowerNodeInternal(IPowerNode node) {
ChunkCoordIntPair chunk = getChunkFromNode(node);
HashMap<AMVector3, PowerNodeEntry> nodeList;
TileEntity te = ((TileEntity) node);
World world = te.getWorldObj();
if (powerNodes.containsKey(chunk)) {
nodeList = powerNodes.get(chunk);
LogHelper.trace("Located Power Node list for chunk %d, %d", chunk.chunkXPos, chunk.chunkZPos);
} else {
LogHelper.trace("Node list not found. Checking cache/files for prior data");
NBTTagCompound compound = PowerNodeCache.instance.getNBTForChunk(world, chunk);
nodeList = new HashMap<AMVector3, PowerNodeEntry>();
if (compound == null || !compound.hasKey("AM2PowerData")) {
powerNodes.put(chunk, nodeList);
LogHelper.trace("Prior node list not found. Created Power Node list for chunk %d, %d", chunk.chunkXPos, chunk.chunkZPos);
} else {
LoadChunkFromNBT(chunk, compound);
nodeList = powerNodes.get(chunk);
//sanity check
if (nodeList == null)
nodeList = new HashMap<AMVector3, PowerNodeEntry>();
LogHelper.trace("Loaded power data for chunk %d, %d", chunk.chunkXPos, chunk.chunkZPos);
}
}
AMVector3 nodeLoc = new AMVector3((TileEntity) node);
//prevent duplicate registrations
if (nodeList.containsKey(nodeLoc))
return nodeList.get(nodeLoc);
PowerNodeEntry pnd = new PowerNodeEntry();
nodeList.put(nodeLoc, pnd);
LogHelper.trace("Successfully registered power node at {%d, %d, %d}", ((TileEntity) node).xCoord, ((TileEntity) node).yCoord, ((TileEntity) node).zCoord);
return pnd;
}
use of am2.api.power.IPowerNode in project ArsMagica2 by Mithion.
the class PowerNodeEntry method validatePath.
private boolean validatePath(World world, LinkedList<AMVector3> path) {
for (AMVector3 vec : path) {
//power can't transfer through unloaded chunks!
Chunk chunk = world.getChunkFromBlockCoords((int) vec.x, (int) vec.z);
if (!chunk.isChunkLoaded)
return false;
TileEntity te = world.getTileEntity((int) vec.x, (int) vec.y, (int) vec.z);
//if valid, continue the loop, otherwise return false.
if (te != null && te instanceof IPowerNode)
continue;
//set a marker block to say that a conduit or other power relay of some sort was here and is now not
if (!world.isRemote && world.isAirBlock((int) vec.x, (int) vec.y, (int) vec.z)) {
world.setBlock((int) vec.x, (int) vec.y, (int) vec.z, BlocksCommonProxy.brokenLinkBlock);
}
return false;
}
//if we're here, then all locations checked out
return true;
}
use of am2.api.power.IPowerNode in project ArsMagica2 by Mithion.
the class PowerNodeEntry method requestPowerFrom.
private float requestPowerFrom(World world, LinkedList<AMVector3> path, PowerTypes type, float amount) {
if (!validatePath(world, path))
return 0f;
AMVector3 end = path.getLast();
TileEntity te = world.getTileEntity((int) end.x, (int) end.y, (int) end.z);
if (te != null && te instanceof IPowerNode) {
if (((IPowerNode) te).canProvidePower(type)) {
return PowerNodeRegistry.For(world).consumePower(((IPowerNode) te), type, amount);
}
}
return 0f;
}
Aggregations