Cuberite Forum
Redstone Simulator Rewrite - Printable Version

+- Cuberite Forum (https://forum.cuberite.org)
+-- Forum: Cuberite (https://forum.cuberite.org/forum-4.html)
+--- Forum: Development (https://forum.cuberite.org/forum-13.html)
+--- Thread: Redstone Simulator Rewrite (/thread-1247.html)

Pages: 1 2 3 4 5 6 7


Redstone Simulator Rewrite - tigerw - 09-21-2013

Привет!

I am rewriting the redstone simulator because the current one doesn't work.

However, I am encountering a difficulty (namely, an assert fired by deque) trying to get blocks to be powered or changed as a result of being powered. This only happens in DEBUG and not release.

The assert fired tells me: Expression: deque iterator not incrementable

What is the cause of this?

This code, for example, breaks:

void cRedstoneSimulator::HandleTNT(const Vector3i & a_BlockPos)
{
	if (AreCoordsPowered(a_BlockPos))
	{
		m_World.BroadcastSoundEffect("random.fuse", a_BlockPos.x * 8, a_BlockPos.y * 8, a_BlockPos.z * 8, 0.5f, 0.6f);
		m_World.SpawnPrimedTNT(a_BlockPos.x + 0.5, a_BlockPos.y + 0.5, a_BlockPos.z + 0.5, 4);  // 4 seconds to boom
		m_World.SetBlock(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z, E_BLOCK_AIR, 0);
	}
	return;
}
bool cRedstoneSimulator::AreCoordsPowered(const Vector3i & a_BlockPos)
{
	for (PoweredBlocksList::iterator itr = m_PoweredBlocks.begin(); itr != m_PoweredBlocks.end(); ++itr)
	{
		sPoweredBlocks & Change = *itr;

		if (Change.a_BlockPos.Equals(a_BlockPos))
		{
			return true;
		}
	}
	return false;
}



RE: Redstone Simulator Rewrite - xoft - 09-22-2013

Здравствуй.
This means that your code is buggy. The assert means that you have an iterator that is invalid; this usually happens when iterating through a container and deleting from the container at the same time, either from two threads, or even from one thread. You cannot have a for-loop over the container, inside which you delete items from that container - this invalidates the iterators.
I don't think the code that you've posted is the only cause of this, there's nothing immediate that would indicate a problem.

Of course the asserts only fire in debug mode, that's the point of asserts - they check conditions that shouldn't happen and may be costly to check, so they are compiled in only in debug mode; in release they are left out, meaning the program will crash or otherwise misbehave instead.


RE: Redstone Simulator Rewrite - tigerw - 09-22-2013

I see Smile

So how would I iterate through a BlockList and delete the ones I don't want?


RE: Redstone Simulator Rewrite - xoft - 09-22-2013

Basically you need something like this (skeleton only):
for (itr = Container.begin; itr != Container.end(); )  // Note that you need to call end() each time, and you cannot auto-advance itr
{
  if (ShouldDelete)
  {
     itr = Container.erase(itr);  // Container must support erasing
  }
  else
  {
    ++itr;
  }
}



RE: Redstone Simulator Rewrite - tigerw - 09-22-2013

Thanks!

Found two:

// Check to see if PoweredBlocks have invalid items (source is air)
	for (PoweredBlocksList::iterator itr = m_PoweredBlocks.begin(); itr != m_PoweredBlocks.end(); )
	{
		sPoweredBlocks & Change = *itr;

		if (m_World.GetBlock(Change.a_SourcePos) == E_BLOCK_AIR)
		{
			itr = m_PoweredBlocks.erase(itr);
		}
		else if (
			((m_World.GetBlock(Change.a_SourcePos) == E_BLOCK_REDSTONE_WIRE) && (m_World.GetBlockMeta(Change.a_SourcePos) == 0)) ||
			(m_World.GetBlock(Change.a_SourcePos) == E_BLOCK_REDSTONE_TORCH_OFF) ||
			(m_World.GetBlock(Change.a_SourcePos) == E_BLOCK_REDSTONE_REPEATER_OFF) ||
			(m_World.GetBlock(Change.a_SourcePos) == E_BLOCK_INACTIVE_COMPARATOR)
			)
		{
			itr = m_PoweredBlocks.erase(itr);
		}
		else
		{
			itr++;
		}
	}


...and a SetBlock to FastSetBlock.


RE: Redstone Simulator Rewrite - tigerw - 09-24-2013

Hello, I need halp againBig Grin

How do I get a Chunk (pointer? object?) to pass onto cRedStoneSimulator::WakeUp(int X Y Z, cChunk & a_Chunk)? I need to wake it up manually to provide an update to devices.

Thanks.


RE: Redstone Simulator Rewrite - xoft - 09-24-2013

cWorld:DoWithChunk()

Where are you calling that WakeUp from? Doesn't that have a chunk?

To be honest, I think you've bitten off quite a bit more than you could chew here. Rewriting redstone is a really really big task, and with your history of doing things half-way through, then abandoning them, I'm not really comfortable with it all.

There are lots of other tasks, especially in the FlySpray, that I believe would be more suitable for you now.


RE: Redstone Simulator Rewrite - tigerw - 09-24-2013

(09-24-2013, 05:37 AM)xoft Wrote: ...and with your history of doing things half-way through...

Thank you, for summing that upTongue

I don't know, it's going alright. Besides, the FlySpray issues seem to mainly consist of crash bugs (no idea how to debug), physics (tried, failed, lost some hair), and redstone.

I might as well try, right?

WakeUp is called by the server, I just need to call it again to update blocks that were changed as a result of simulation (FastSetBlock doesn't seem to do it automatically)

Owait, I can just do m_World.WakeUpSimulators, right?

This simplifies things!

Or not. Deque iterators are derpy.


RE: Redstone Simulator Rewrite - xoft - 09-24-2013

FlySpray issues that I think would be an ideal match for you:
Door/Fence Door open without permission. (#260)
Fire should activate TNT (#406)
Bucket should use the "BlockFace == -1" packet (#405)
Pickup collection range too long (#396)
Add pickup delay (#394) (don't you just LOVE pickups? Wink )
Add rotation and mirroring support to cBlockArea (#331)
The Core won't let player interact with the block on which they're standing (#188) - This one bugs me really bad
Snow should melt in high blocklight (#264)

Why do you even need to call the wakeup again? It feels as if you're trying to do something silly, how about you share your thoughts on this? What are you trying to achieve? Why did you pick this solution?


RE: Redstone Simulator Rewrite - tigerw - 09-24-2013

I need to update each redstone wire that is connected. I have managed to (nearly) achieve this with recursing the HandleRedstoneWire function and changes to WakeUp, but the last block of wire doesn't update for some reason.

I will go on to pickup delays soon - but I don't know how to pass a bool from SpawnItemPickups to the pickup handler (it complains about default values or something).

I think I will remove the Core block interaction code, because it doesn't actually do anything - i.e. I can still place a block in ANOTHER player if the server hasn't updated their position correctly. All Core does is check if the block being placed is intersecting YOURSELF, which the client already does, so is effectively useless.