Jump to content

Trigger a search down a line of blocks (cables) [UNSOLVED] [1.7.10] [CONTINUED]


TheEpicTekkit

Recommended Posts

This is a continuation of my previous topic; Trigger a search down a line of blocks.

 

Hello everyone.

 

So, I am working on a cable, and I have all but finding power emitters working. So what I need to do, is if a machine is requesting power, it will search for a cable on any of its six sides, if it finds one, one of three things (I am not sure which would be best) would happen.

One, the only thing the block does is trigger a search on the cable, and from there the cable scans down any other cables connected, remembering the location of the requesting block, and passing it to each cable, then if the cable locates a power emitter, will send its location back to the requesting block, and then the requesting block draws power from the emitter.

Two, the cables act as a guide for the requesting block, and a graphical connection for the player. What I mean by guide is the requesting block does all the searching, and the cables are what it follows. So first it will scan for cables immediately adjacent to it, then if it finds one, will search for cables immediately adjacent to that cable, and if it finds a cable immediately adjacent to that one, it will scan for cables around it, etc, until it finds an energy emitter. If the requesting machine finds a cable with more than one cable attached to it, it will scan around all of them (same for if it finds more that one cable directly adjacent to it) and will choose the energy emitter that it finds first.

Three, there is no scanning being done, each cable has an internal buffer of power, and it just passes that power onto the next cable. (I really dont want to do this one, but if it comes to it, I will. This method doesn't seem very flexible with what I can do with the energy)

 

Currently I have been working on the first option, but it is proving more difficult than I expected. Either, the cable doesnt actually scan down the line, and can only detect blocks directly attached to the cable, or I get a stackOverflowError because the cable searches, finds a cable adjacent, triggers a method in the tileentity of the found cable that then restarts the method that found that cable in the first place, thus getting stuck in a loop, and crashing.

 

So, my question is which one of these methods would be the best choice? and how would I go about doing the best method?

 

Thanks for the help.

I ask complicated questions, and apparently like to write really long detailed posts. But I also help others when I can.

Link to comment
Share on other sites

Anyway....

 

not saying TGG is wrong, but if you need somewhere to hold the network why not a block that does just that? The fusebox hold all the mapping information, and routes to machines and power sources, and only things that need power will make a request to the fusebox, and the fuse box will check to see if it is valid (connections, etc) and send the response. That way most players will have 1 fusebox, and just hook everything to it, plus you can have things like fuses that might blow if too much power is going through it ;). kinda like how IC has machines explode if too much power goes to them, only now you have a chance to prevent that with fuses.

 

Either way it is whatever works best for you and the mod.

 

Yeah, I can add cool functionality with my network. And as I said before, no other mods that I know of do this.

 

So the way I see it working, is a bit like Applied Energistics, my fuse box is like the me controller. (Okay, I just contradicted myself, apparently I can think of a mod that does something similar xD ) So, the player connects a wire from a network of machines they have to the fuse box, and they can all communicate with each other.

 

So I have another problem. So the way this pathfinding library works is the pathfinder (it comes witn 4 different algorithms that I can use; A-Star, Depth First Search (DFS) Breadth First Search (BFS) and Dijkstra) the pathfinder works by a target node id (the node it will try to find a route to) and a start node (the node that it will start from). The problem is how do I assign and manage these IDs? No two machines in the world can have the same node ID, otherwise the new node ID will overwrite the old one. And, how do I make the machine that is requesting power choose a node ID that is in the same network as it is in without already having done a scan of the network (which then would be impossible as no node IDs are known).

I ask complicated questions, and apparently like to write really long detailed posts. But I also help others when I can.

Link to comment
Share on other sites

Like I mentioned the fuse box actually does all the scanning, and mapping + route making. So the fuseBox tileEntity will hold these lists (and save so on world load and such) then a machine will look for a fuseBox (note only things that *need* power will look, special cases are if you have a powerStorage that can input and output) the machine will access the fuseBox's list of powerSources (remember I was going onabout saving the location of a powerSource and the route of cables(that you would find with A*))

 

and try the route (check to make sure all cables still exist, and that the 1st and last connect to the fusebox(1st) and emitter(last). Since A* I would think you'd start from the box and go to the emitter) if the route is still good, attempt to draw power, if that is good well draw power, if either of those clauses fail, move to the next "powerRoute"(which is a different emitter, that may, or maynot share the same cable route)

 

in the cases where the machine can't find a route the fuseBox should be notified about this to A) try to find a route, or B) in the case of a broken or false route, reroute. And if that fails remove from the list

 

normally the fuseBox will every now and then ensure that everything is up to date (cable map is still good, or say fk the map and check the cables whenever needed (that will be one less thing to store in memory) and routes are the only saved cable lines) it will also check for any new emitters or machines and ensure that there is a route, and if there is one, is it still good. But that should probably happen every min or so.

 

Also do you mean nodes are the emitters (generator, battery) or you mean like a RL network (Modem, Cat-5 cable, switch/router, cat-5*ports+targets,target) the switch/router being the node?

 

or are you thinking that each Node will keep a list of everything connected to it? (Node 1 is connected to 2 generators, and Node 2 and 3) then a fuse box can say "well to get to generator 2, to power machine 1(machine one being connected to node 4) is I have to route power through nodes 4, 3, and 1 all the while getting the fastest cable route between them all?

Link to comment
Share on other sites

By node, I mean any block that can interact with energy (implements IEnergyHandler) this doesn't include cables. So, generators, machines, and stores, this allows other mods that use the api I havn't set up yet to add blocks that interact with the network. For the fuse box to be able to tell if a node is an emitter, machine, or store, the node will have an enum ID saying emitter, consumer (machine) and store.

 

Another interesting scenario that I haven't considered (yet again) what if there are multiple fuse boxes connected to the network? how would a node decide which fuse box to use? it cant just use the closest, because that means that some machines will use one, and others will use another, and this will cause problems. Also, what if a fuse box has more than one network connected to it? like for example, there is a cable on one side leading to one network, and there is another cable on the other side, not connected to the first network at all, leading to a separate network.

 

Btw, Hugo, you have been really helpful, none of my other topics have got this much help from one person :D

I ask complicated questions, and apparently like to write really long detailed posts. But I also help others when I can.

Link to comment
Share on other sites

I was almost thinking that nearby fuseBoxes idk radius of 20 blocks? maybe less, (just so close together fuseBoxes don't remake the same network they more or less say "fuseBox number one will be the leader, we will merely reference him" and as for network collision.. hmm. Maybe since you say the range of your longest cable is 60 blocks, it will look for other fuseboxes twice that range? Idk this was not something I had thought of, good call.

 

I was hoping (andyes I still understand you can  never hop that another human being will do what they are suppose to do) that players would have one fuseBox and have something like Room A is the power generation and storage room, and Room B is the machine room with a FuseBox inbetween the two rooms. Cables in, cables out.

Link to comment
Share on other sites

I have to be honest and say tl;dr, so if I'm way off forgive me...

 

But what I would do is make a method within your class that can determine distance from any coordinate, and derive your power rating from that. Ie: 0,59,0 is 59 from 0,0,0; power = 59 - distance, aka 1. Then do a typical block search starting at your trigger block, which returns success when it finds an emitter (which will then enact the distance/power method), and terminates when no cable can be found.

 

Click block...

begin loop

check all six sides

found cable east...

(ignore west, check 5 sides)...

found cable south...

(ignore north, check 5 sides)...

found emitter south...

determine distance (3)...

determine power (57)...

end

 

Has this not been suggested/will it not work for your issue?

I'll need help, and I'll give help. Just ask, you know I will!

Link to comment
Share on other sites

I have to be honest and say tl;dr, so if I'm way off forgive me...

 

But what I would do is make a method within your class that can determine distance from any coordinate, and derive your power rating from that. Ie: 0,59,0 is 59 from 0,0,0; power = 59 - distance, aka 1. Then do a typical block search starting at your trigger block, which returns success when it finds an emitter (which will then enact the distance/power method), and terminates when no cable can be found.

 

Click block...

begin loop

check all six sides

found cable east...

(ignore west, check 5 sides)...

found cable south...

(ignore north, check 5 sides)...

found emitter south...

determine distance (3)...

determine power (57)...

end

 

Has this not been suggested/will it not work for your issue?

 

Sorry, but I don't understand what you mean....

I ask complicated questions, and apparently like to write really long detailed posts. But I also help others when I can.

Link to comment
Share on other sites

If you really want to use cables and stuff, the second option, in my opinion, is the best. You sould have an array for each tile cable's tile entity, with 6 values, each one corresponding to a ForgeDirection.[direction]. Each values could be either null or a direction. Then, the recieving block would look for a cable connected to it, get the tile entity's coordinates, look for every array value and see which ones are not null. Then, according to the "not null" values, it would take the tile entity's coordinates and add/subtract 1 and see if there was another pipe. This would continue until the suppose pipe is a power-emitter block. You should have a internal buffer for the cables, preventing the instant-transmitting power situation. For example, if the power-emiter block had 3000 energy and the power-requesting block had an internal storage of 6000 energy and it was empy, then, in one tick, the 3000 energy in the power-emitter block would go into the power-requesting block, which would be a bad thing, in my opinion. Hope I was lucid with this part. ;)

If you are interested, you could do something like I'm doing with my mod. The power emitter block could search for a power-recieving block in a certain area and if it finds it, it will transmit power, slowly but surely, as you wish. Realy hope I was useful. :)

Link to comment
Share on other sites

Its similar to your first approach, but I feel you are overcomplicating it. Do it all from the trigger block with classic logic/iteration.

 

I'll write some shorthand code...

 

Coordinate scan(coordinate){ scans your 6 sides and returns the coordinates of a found cable or null }

Coordiante start = trigger block coord;
Coordinate temp = start;
Coordinate find = null;
Coordiate ignore = null;

find = Scan(start);
if find != null{
if find is emitter, yippee! else ignore = temp, temp = find, find = scan(temp); 

rinse/repeat

 

Then when you find an emitter, determine the distance of emitter from start, and derive your power or whatever from there...

I'll need help, and I'll give help. Just ask, you know I will!

Link to comment
Share on other sites

e__________r  Will give you StackOverflow.

      |___|

 

Good call.

 

In that case, although it would be a bit long-winded, I would ignore the cables and find any within a radius, and then work backward to try to find a cable path that leads back. You would want to make a List<> of already scanned cables, but treat tees specially. That would actually be some fun logic, and would work similar to AI pathing. That's all I've got! lol

I'll need help, and I'll give help. Just ask, you know I will!

Link to comment
Share on other sites

e__________r

      |___|

How would this result in a StackOverflow? The way I am scanning the network is with an A-Star algorithm to find the shortest route from one node to another, and a DFS or BFS (haven't decided which yet) algorithm to locate the nodes in the first place.

I ask complicated questions, and apparently like to write really long detailed posts. But I also help others when I can.

Link to comment
Share on other sites

I don't quite understand why this doesn't work, I want the cable to scan around itself, and if it finds a cable, trigger the scan method on that cable with one less range, so it should go for 40 blocks.

 [s]
        public int scanRange = 40;


public void scan(World world, int x, int y, int z, int remaining, List<TileEntity> map) {
	TileEntity tile = world.getTileEntity(x, y, z);
	List<TileEntity> networkMap = new ArrayList<TileEntity>();

	while (remaining != 0) {
		if (tile instanceof IEnergyHandler) {
			networkMap.add(tile);
		} if (tile instanceof TileEntityCable) {
			((TileEntityCable) tile).scan(world, x, y, z, this.scanRange - 1, networkMap); //Re-Triggering the scan on the next cable with a new weight (int remaining), and passing on the current known list of IEnergyHandlers
			((TileEntityCable) tile).scanRange = this.scanRange - 1;
			this.scanRange = 0;
		}
	}
}

public void triggerScan() {
	List<TileEntity> map = new ArrayList<TileEntity>();
	map.clear();
	this.scan(worldObj, xCoord + 1, yCoord, zCoord, this.scanRange, map);
	this.scan(worldObj, xCoord - 1, yCoord, zCoord, this.scanRange, map);
	this.scan(worldObj, xCoord, yCoord + 1, zCoord, this.scanRange, map);
	this.scan(worldObj, xCoord, yCoord - 1, zCoord, this.scanRange, map);
	this.scan(worldObj, xCoord, yCoord, zCoord + 1, this.scanRange, map);
	this.scan(worldObj, xCoord, yCoord, zCoord - 1, this.scanRange, map);
}

public void reset() {
	this.scanRange = 40;
} [/s]

And, this method is called 6 times, x + 1, x - 1, y + 1, y - 1, z + 1, and z - 1.

 

Now, I haven't included it, but I have been testing this by making the cable scan around itself, trigger the scan on the next cable (not working) and then setting any adjacent IEnergyHandlers to stone. So, what should be happening is all the IEnergyHandlers connected to the network should turn to stone. Now, all that seems to be happening is only the first cable sets any surrounding IEnergyHandlers to stone. The way I am triggering the scan in the first place, is I have a certain block (Fuse Box) that when placed next to a cable, will trigger the scan.

I ask complicated questions, and apparently like to write really long detailed posts. But I also help others when I can.

Link to comment
Share on other sites

Actually, this has for some reason just decided to not work at all, it is now giving a stackOverflow when it wasn't before.

 

So, scrap that idea, I am going to try this:

 

Two, the cables act as a guide for the requesting block, and a graphical connection for the player. What I mean by guide is the requesting block does all the searching, and the cables are what it follows. So first it will scan for cables immediately adjacent to it, then if it finds one, will search for cables immediately adjacent to that cable, and if it finds a cable immediately adjacent to that one, it will scan for cables around it, etc, until it finds an energy emitter. If the requesting machine finds a cable with more than one cable attached to it, it will scan around all of them (same for if it finds more that one cable directly adjacent to it) and will choose the energy emitter that it finds first.

 

as That One Guy said:

 

If you really want to use cables and stuff, the second option, in my opinion, is the best. You sould have an array for each tile cable's tile entity, with 6 values, each one corresponding to a ForgeDirection.[direction]. Each values could be either null or a direction. Then, the recieving block would look for a cable connected to it, get the tile entity's coordinates, look for every array value and see which ones are not null. Then, according to the "not null" values, it would take the tile entity's coordinates and add/subtract 1 and see if there was another pipe. This would continue until the suppose pipe is a power-emitter block. You should have a internal buffer for the cables, preventing the instant-transmitting power situation. For example, if the power-emiter block had 3000 energy and the power-requesting block had an internal storage of 6000 energy and it was empy, then, in one tick, the 3000 energy in the power-emitter block would go into the power-requesting block, which would be a bad thing, in my opinion. Hope I was lucid with this part. ;)

If you are interested, you could do something like I'm doing with my mod. The power emitter block could search for a power-recieving block in a certain area and if it finds it, it will transmit power, slowly but surely, as you wish. Realy hope I was useful. :)

I didn't actually see this reply before, and yes, this was really helpful. Thanks.

 

I actually think this is looking like my best option now.

 

Also, I already have that array of connections. I am using it to determine weather to render the connections between cables or not. So, I could just use that. The only problem is that sometimes on world load, or chunk load, some of the connections will have disappeared, and I need to update the block to reconnect them. I could be checking the connections in updateEntity (which I was doing, but was noticing a framerate drop in doing so, so changed it to update connections in onBlockAdded, breakBlock, and onNeighborBlockChange) and when I was using updateEntity, I didn't have any problems with the cables disconnecting, so I need a way to fix this. I think I will make it re check the connections every couple of seconds, I just need to know how to count how many ticks have passed.

I ask complicated questions, and apparently like to write really long detailed posts. But I also help others when I can.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.