Redstone Megacommit [SEE DESC]

+ Updated BlockID - look for yourself
* Improved button, repeater, lever, and comparator code ->
simplification and splitting of some stuff from the redstone simulator
file
* Fixed buttons not breaking when in an invalid game state
* Fixed QueueSetBlock -> improved (AGAIN) piston code
+ Rewrote redstone simulator

Fixes: #57, #58, #205, and part of #131.
Fixes FS issues: 281, 116, and 102
master
Tiger Wang 2013-11-18 22:30:34 +00:00
parent b5821998b4
commit bc1e236d54
16 changed files with 1143 additions and 1098 deletions

View File

@ -669,13 +669,13 @@ public:
g_BlockTransparent[E_BLOCK_FLOWER_POT] = true;
g_BlockTransparent[E_BLOCK_GLASS] = true;
g_BlockTransparent[E_BLOCK_GLASS_PANE] = true;
g_BlockTransparent[E_BLOCK_STAINED_GLASS] = true;
g_BlockTransparent[E_BLOCK_STAINED_GLASS_PANE] = true;
g_BlockTransparent[E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE] = true;
g_BlockTransparent[E_BLOCK_ICE] = true;
g_BlockTransparent[E_BLOCK_IRON_DOOR] = true;
g_BlockTransparent[E_BLOCK_LAVA] = true;
g_BlockTransparent[E_BLOCK_LEAVES] = true;
g_BlockTransparent[E_BLOCK_LEVER] = true;
g_BlockTransparent[E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE] = true;
g_BlockTransparent[E_BLOCK_MELON_STEM] = true;
g_BlockTransparent[E_BLOCK_NETHER_BRICK_FENCE] = true;
g_BlockTransparent[E_BLOCK_NEW_LEAVES] = true;
@ -687,6 +687,8 @@ public:
g_BlockTransparent[E_BLOCK_RED_MUSHROOM] = true;
g_BlockTransparent[E_BLOCK_SIGN_POST] = true;
g_BlockTransparent[E_BLOCK_SNOW] = true;
g_BlockTransparent[E_BLOCK_STAINED_GLASS] = true;
g_BlockTransparent[E_BLOCK_STAINED_GLASS_PANE] = true;
g_BlockTransparent[E_BLOCK_STATIONARY_LAVA] = true;
g_BlockTransparent[E_BLOCK_STATIONARY_WATER] = true;
g_BlockTransparent[E_BLOCK_STONE_PRESSURE_PLATE] = true;
@ -700,7 +702,7 @@ public:
// TODO: Any other transparent blocks?
// One hit break blocks
// One hit break blocks:
g_BlockOneHitDig[E_BLOCK_ACTIVE_COMPARATOR] = true;
g_BlockOneHitDig[E_BLOCK_BIG_FLOWER] = true;
g_BlockOneHitDig[E_BLOCK_BROWN_MUSHROOM] = true;
@ -711,7 +713,6 @@ public:
g_BlockOneHitDig[E_BLOCK_FLOWER] = true;
g_BlockOneHitDig[E_BLOCK_FLOWER_POT] = true;
g_BlockOneHitDig[E_BLOCK_INACTIVE_COMPARATOR] = true;
g_BlockOneHitDig[E_BLOCK_LOCKED_CHEST] = true;
g_BlockOneHitDig[E_BLOCK_MELON_STEM] = true;
g_BlockOneHitDig[E_BLOCK_POTATOES] = true;
g_BlockOneHitDig[E_BLOCK_PUMPKIN_STEM] = true;
@ -727,7 +728,7 @@ public:
g_BlockOneHitDig[E_BLOCK_TALL_GRASS] = true;
g_BlockOneHitDig[E_BLOCK_TORCH] = true;
// Blocks that breaks when pushed by piston
// Blocks that break when pushed by piston:
g_BlockPistonBreakable[E_BLOCK_ACTIVE_COMPARATOR] = true;
g_BlockPistonBreakable[E_BLOCK_AIR] = true;
g_BlockPistonBreakable[E_BLOCK_BED] = true;
@ -765,11 +766,12 @@ public:
g_BlockPistonBreakable[E_BLOCK_TORCH] = true;
g_BlockPistonBreakable[E_BLOCK_VINES] = true;
g_BlockPistonBreakable[E_BLOCK_WATER] = true;
g_BlockPistonBreakable[E_BLOCK_WOODEN_BUTTON] = true;
g_BlockPistonBreakable[E_BLOCK_WOODEN_DOOR] = true;
g_BlockPistonBreakable[E_BLOCK_WOODEN_PRESSURE_PLATE] = true;
// Blocks that can be snowed over:
// Blocks that cannot be snowed over:
g_BlockIsSnowable[E_BLOCK_ACTIVE_COMPARATOR] = false;
g_BlockIsSnowable[E_BLOCK_AIR] = false;
g_BlockIsSnowable[E_BLOCK_BIG_FLOWER] = false;
@ -785,7 +787,6 @@ public:
g_BlockIsSnowable[E_BLOCK_INACTIVE_COMPARATOR] = false;
g_BlockIsSnowable[E_BLOCK_LAVA] = false;
g_BlockIsSnowable[E_BLOCK_LILY_PAD] = false;
g_BlockIsSnowable[E_BLOCK_LOCKED_CHEST] = false;
g_BlockIsSnowable[E_BLOCK_REDSTONE_REPEATER_OFF] = false;
g_BlockIsSnowable[E_BLOCK_REDSTONE_REPEATER_ON] = false;
g_BlockIsSnowable[E_BLOCK_REDSTONE_TORCH_OFF] = false;
@ -796,6 +797,8 @@ public:
g_BlockIsSnowable[E_BLOCK_SAPLING] = false;
g_BlockIsSnowable[E_BLOCK_SIGN_POST] = false;
g_BlockIsSnowable[E_BLOCK_SNOW] = false;
g_BlockIsSnowable[E_BLOCK_STAINED_GLASS] = false;
g_BlockIsSnowable[E_BLOCK_STAINED_GLASS_PANE] = false;
g_BlockIsSnowable[E_BLOCK_STATIONARY_LAVA] = false;
g_BlockIsSnowable[E_BLOCK_STATIONARY_WATER] = false;
g_BlockIsSnowable[E_BLOCK_TALL_GRASS] = false;
@ -806,7 +809,7 @@ public:
g_BlockIsSnowable[E_BLOCK_WATER] = false;
// Blocks that don't drop without a special tool
// Blocks that don't drop without a special tool:
g_BlockRequiresSpecialTool[E_BLOCK_BRICK] = true;
g_BlockRequiresSpecialTool[E_BLOCK_CAULDRON] = true;
g_BlockRequiresSpecialTool[E_BLOCK_COAL_ORE] = true;
@ -841,7 +844,7 @@ public:
g_BlockRequiresSpecialTool[E_BLOCK_STONE_SLAB] = true;
g_BlockRequiresSpecialTool[E_BLOCK_VINES] = true;
// Nonsolid Blocks:
// Nonsolid blocks:
g_BlockIsSolid[E_BLOCK_ACTIVATOR_RAIL] = false;
g_BlockIsSolid[E_BLOCK_AIR] = false;
g_BlockIsSolid[E_BLOCK_BIG_FLOWER] = false;
@ -860,11 +863,8 @@ public:
g_BlockIsSolid[E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE] = false;
g_BlockIsSolid[E_BLOCK_MELON_STEM] = false;
g_BlockIsSolid[E_BLOCK_NETHER_PORTAL] = false;
g_BlockIsSolid[E_BLOCK_PISTON] = false;
g_BlockIsSolid[E_BLOCK_PISTON_EXTENSION] = false;
g_BlockIsSolid[E_BLOCK_RAIL] = false;
g_BlockIsSolid[E_BLOCK_REDSTONE_REPEATER_OFF] = false;
g_BlockIsSolid[E_BLOCK_REDSTONE_REPEATER_ON] = false;
g_BlockIsSolid[E_BLOCK_REDSTONE_TORCH_OFF] = false;
g_BlockIsSolid[E_BLOCK_REDSTONE_TORCH_ON] = false;
g_BlockIsSolid[E_BLOCK_REDSTONE_WIRE] = false;
@ -887,7 +887,7 @@ public:
g_BlockIsSolid[E_BLOCK_WOODEN_PRESSURE_PLATE] = false;
g_BlockIsSolid[E_BLOCK_WOODEN_SLAB] = false;
// Torch placeable
// Torch placeable blocks:
g_BlockIsTorchPlaceable[E_BLOCK_BEDROCK] = true;
g_BlockIsTorchPlaceable[E_BLOCK_BLOCK_OF_COAL] = true;
g_BlockIsTorchPlaceable[E_BLOCK_BLOCK_OF_REDSTONE] = true;
@ -933,7 +933,7 @@ public:
g_BlockIsTorchPlaceable[E_BLOCK_NETHER_QUARTZ_ORE] = true;
g_BlockIsTorchPlaceable[E_BLOCK_NOTE_BLOCK] = true;
g_BlockIsTorchPlaceable[E_BLOCK_OBSIDIAN] = true;
g_BlockIsTorchPlaceable[E_BLOCK_PACKED_ICE] = true;
g_BlockIsTorchPlaceable[E_BLOCK_PACKED_ICE] = true;
g_BlockIsTorchPlaceable[E_BLOCK_PLANKS] = true;
g_BlockIsTorchPlaceable[E_BLOCK_PUMPKIN] = true;
g_BlockIsTorchPlaceable[E_BLOCK_QUARTZ_BLOCK] = true;
@ -955,3 +955,4 @@ public:

View File

@ -17,21 +17,14 @@ cBlockButtonHandler::cBlockButtonHandler(BLOCKTYPE a_BlockType)
void cBlockButtonHandler::OnUse(cWorld *a_World, cPlayer *a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ)
{
// Flip the ON bit on/off. Using XOR bitwise operation to turn it on/off.
// Flip the ON bit on/off using the XOR bitwise operation
NIBBLETYPE Meta = ((a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) ^ 0x08) & 0x0f);
a_World->SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta);
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, Meta);
a_World->BroadcastSoundEffect("random.click", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, (Meta & 0x08) ? 0.6f : 0.5f);
if (Meta & 0x08)
{
a_World->BroadcastSoundEffect("random.click", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, 0.6f);
}
else
{
a_World->BroadcastSoundEffect("random.click", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, 0.5f);
}
// Queue a button reset (unpress), with a GetBlock to prevent duplication of buttons (press, break, wait for reset)
a_World->QueueSetBlock(a_BlockX, a_BlockY, a_BlockZ, a_World->GetBlock(a_BlockX, a_BlockY, a_BlockZ), ((a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) ^ 0x08) & 0x0f), m_BlockType == E_BLOCK_STONE_BUTTON ? 20 : 25);
// Queue a button reset (unpress)
a_World->QueueSetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, ((a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) ^ 0x08) & 0x0f), m_BlockType == E_BLOCK_STONE_BUTTON ? 20 : 30);
}

View File

@ -14,11 +14,11 @@ public:
virtual void OnUse(cWorld * a_World, cPlayer * a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ) override;
virtual void ConvertToPickups(cItems & a_Pickups, NIBBLETYPE a_BlockMeta) override
{
// Reset meta to 0
a_Pickups.push_back(cItem(m_BlockType == E_BLOCK_WOODEN_BUTTON ? E_BLOCK_WOODEN_BUTTON : E_BLOCK_STONE_BUTTON, 1, 0));
a_Pickups.push_back(cItem(m_BlockType, 1, 0));
}
@ -51,10 +51,10 @@ public:
{
switch (a_BlockFace)
{
case BLOCK_FACE_ZP: { return 0x4; }
case BLOCK_FACE_ZM: { return 0x3; }
case BLOCK_FACE_XP: { return 0x2; }
case BLOCK_FACE_XM: { return 0x1; }
case BLOCK_FACE_ZM: { return 0x4; }
case BLOCK_FACE_ZP: { return 0x3; }
case BLOCK_FACE_XM: { return 0x2; }
case BLOCK_FACE_XP: { return 0x1; }
default:
{
ASSERT(!"Unhandled block face!");
@ -62,6 +62,30 @@ public:
}
}
}
inline static NIBBLETYPE BlockMetaDataToBlockFace(NIBBLETYPE a_Meta)
{
switch (a_Meta & 0x7)
{
case 0x1: return BLOCK_FACE_XP;
case 0x2: return BLOCK_FACE_XM;
case 0x3: return BLOCK_FACE_ZP;
case 0x4: return BLOCK_FACE_ZM;
default:
{
ASSERT(!"Unhandled block meta!");
return BLOCK_FACE_NONE;
}
}
}
virtual bool CanBeAt(int a_RelX, int a_RelY, int a_RelZ, const cChunk & a_Chunk) override
{
NIBBLETYPE Meta = a_Chunk.GetMeta(a_RelX, a_RelY, a_RelZ);
AddFaceDirection(a_RelX, a_RelY, a_RelZ, BlockMetaDataToBlockFace(Meta), true);
return (a_RelY > 0) && (g_BlockIsSolid[a_Chunk.GetBlock(a_RelX, a_RelY, a_RelZ)]);
}
} ;

View File

@ -1,7 +1,7 @@
#include "Globals.h"
#include "BlockComparator.h"
#include "../Simulator/RedstoneSimulator.h"
#include "BlockRedstoneRepeater.h"
#include "../Entities/Player.h"
@ -44,7 +44,7 @@ bool cBlockComparatorHandler::GetPlacementBlockTypeMeta(
)
{
a_BlockType = m_BlockType;
a_BlockMeta = cRedstoneSimulator::RepeaterRotationToMetaData(a_Player->GetRotation());
a_BlockMeta = cBlockRedstoneRepeaterHandler::RepeaterRotationToMetaData(a_Player->GetRotation());
return true;
}

View File

@ -19,18 +19,11 @@ cBlockLeverHandler::cBlockLeverHandler(BLOCKTYPE a_BlockType)
void cBlockLeverHandler::OnUse(cWorld *a_World, cPlayer *a_Player, int a_BlockX, int a_BlockY, int a_BlockZ, char a_BlockFace, int a_CursorX, int a_CursorY, int a_CursorZ)
{
// Flip the ON bit on/off. Using XOR bitwise operation to turn it on/off.
// Flip the ON bit on/off using the XOR bitwise operation
NIBBLETYPE Meta = ((a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ) ^ 0x08) & 0x0f);
a_World->SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, Meta);
if (Meta & 0x08)
{
a_World->BroadcastSoundEffect("random.click", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, 0.6f);
}
else
{
a_World->BroadcastSoundEffect("random.click", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, 0.5f);
}
a_World->SetBlock(a_BlockX, a_BlockY, a_BlockZ, m_BlockType, Meta);
a_World->BroadcastSoundEffect("random.click", a_BlockX * 8, a_BlockY * 8, a_BlockZ * 8, 0.5f, (Meta & 0x08) ? 0.6f : 0.5f);
}

View File

@ -1,7 +1,6 @@
#pragma once
#include "BlockHandler.h"
#include "../Simulator/RedstoneSimulator.h"
@ -37,11 +36,27 @@ public:
) override
{
a_BlockType = m_BlockType;
a_BlockMeta = cRedstoneSimulator::LeverDirectionToMetaData(a_BlockFace);
a_BlockMeta = LeverDirectionToMetaData(a_BlockFace);
return true;
}
inline static NIBBLETYPE LeverDirectionToMetaData(char a_Dir)
{
// Determine lever direction:
switch (a_Dir)
{
case BLOCK_FACE_TOP: return 0x6;
case BLOCK_FACE_EAST: return 0x1;
case BLOCK_FACE_WEST: return 0x2;
case BLOCK_FACE_SOUTH: return 0x3;
case BLOCK_FACE_NORTH: return 0x4;
case BLOCK_FACE_BOTTOM: return 0x0;
default: return 0x6;
}
}
virtual const char * GetStepSound(void) override
{
return "step.wood";

View File

@ -1,7 +1,6 @@
#include "Globals.h"
#include "BlockRedstoneRepeater.h"
#include "../Simulator/RedstoneSimulator.h"
#include "../Entities/Player.h"
@ -42,7 +41,7 @@ bool cBlockRedstoneRepeaterHandler::GetPlacementBlockTypeMeta(
)
{
a_BlockType = m_BlockType;
a_BlockMeta = cRedstoneSimulator::RepeaterRotationToMetaData(a_Player->GetRotation());
a_BlockMeta = RepeaterRotationToMetaData(a_Player->GetRotation());
return true;
}

View File

@ -48,6 +48,33 @@ public:
{
return "step.wood";
}
inline static NIBBLETYPE RepeaterRotationToMetaData(double a_Rotation)
{
a_Rotation += 90 + 45; // So its not aligned with axis
if (a_Rotation > 360)
{
a_Rotation -= 360;
}
if ((a_Rotation >= 0) && (a_Rotation < 90))
{
return 0x1;
}
else if ((a_Rotation >= 180) && (a_Rotation < 270))
{
return 0x3;
}
else if ((a_Rotation >= 90) && (a_Rotation < 180))
{
return 0x2;
}
else
{
return 0x0;
}
}
} ;

View File

@ -682,18 +682,18 @@ void cChunk::ProcessQueuedSetBlocks(void)
Int64 CurrTick = m_World->GetWorldAge();
for (sSetBlockQueueVector::iterator itr = m_SetBlockQueue.begin(); itr != m_SetBlockQueue.end();)
{
if (itr->m_Tick < CurrTick)
if (itr->m_Tick <= CurrTick)
{
// Current world age is bigger than/equal to target world age - delay time reached
SetBlock(itr->m_RelX, itr->m_RelY, itr->m_RelZ, itr->m_BlockType, itr->m_BlockMeta);
itr = m_SetBlockQueue.erase(itr);
}
else
{
// Not yet
++itr;
continue;
}
else
{
// Now is the time to set the block
SetBlock(itr->m_RelX, itr->m_RelY, itr->m_RelZ, itr->m_BlockType, itr->m_BlockMeta);
itr = m_SetBlockQueue.erase(itr);
}
} // for itr - m_SetBlockQueue[]
}

View File

@ -6,6 +6,7 @@
#include "Simulator/FireSimulator.h"
#include "Simulator/SandSimulator.h"
#include "Simulator/RedstoneSimulator.h"
@ -338,6 +339,7 @@ public:
cFluidSimulatorData * GetWaterSimulatorData(void) { return m_WaterSimulatorData; }
cFluidSimulatorData * GetLavaSimulatorData (void) { return m_LavaSimulatorData; }
cSandSimulatorChunkData & GetSandSimulatorData (void) { return m_SandSimulatorData; }
cRedstoneSimulatorChunkData & GetRedstoneSimulatorData(void) { return m_RedstoneSimulatorData; }
cBlockEntity * GetBlockEntity(int a_BlockX, int a_BlockY, int a_BlockZ);
cBlockEntity * GetBlockEntity(const Vector3i & a_BlockPos) { return GetBlockEntity(a_BlockPos.x, a_BlockPos.y, a_BlockPos.z); }
@ -407,6 +409,7 @@ private:
cFluidSimulatorData * m_WaterSimulatorData;
cFluidSimulatorData * m_LavaSimulatorData;
cSandSimulatorChunkData m_SandSimulatorData;
cRedstoneSimulatorChunkData m_RedstoneSimulatorData;
// pick up a random block of this chunk

View File

@ -2,7 +2,7 @@
#pragma once
#include "ItemHandler.h"
#include "../Simulator/RedstoneSimulator.h"
#include "../Blocks/BlockRedstoneRepeater.h"
@ -30,7 +30,7 @@ public:
) override
{
a_BlockType = E_BLOCK_INACTIVE_COMPARATOR;
a_BlockMeta = cRedstoneSimulator::RepeaterRotationToMetaData(a_Player->GetRotation());
a_BlockMeta = cBlockRedstoneRepeaterHandler::RepeaterRotationToMetaData(a_Player->GetRotation());
return true;
}
} ;

View File

@ -2,7 +2,7 @@
#pragma once
#include "ItemHandler.h"
#include "../Simulator/RedstoneSimulator.h"
#include "../Blocks/BlockRedstoneRepeater.h"
@ -30,7 +30,7 @@ public:
) override
{
a_BlockType = E_BLOCK_REDSTONE_REPEATER_OFF;
a_BlockMeta = cRedstoneSimulator::RepeaterRotationToMetaData(a_Player->GetRotation());
a_BlockMeta = cBlockRedstoneRepeaterHandler::RepeaterRotationToMetaData(a_Player->GetRotation());
return true;
}
} ;

View File

@ -14,14 +14,8 @@
extern bool g_BlockPistonBreakable[];
/// Number of ticks that the piston extending / retracting waits before setting the block
const int PISTON_TICK_DELAY = 20;
const int PISTON_TICK_DELAY = 6;
@ -120,7 +114,7 @@ void cPiston::ExtendPiston(int pistx, int pisty, int pistz)
AddDir(pistx, pisty, pistz, pistonMeta, -1);
// "pist" now at piston body, "ext" at future extension
m_World->QueueSetBlock( pistx, pisty, pistz, pistonBlock, pistonMeta | 0x8, PISTON_TICK_DELAY);
m_World->SetBlock( pistx, pisty, pistz, pistonBlock, pistonMeta | 0x8);
m_World->QueueSetBlock(extx, exty, extz, E_BLOCK_PISTON_EXTENSION, pistonMeta | (IsSticky(pistonBlock) ? 8 : 0), PISTON_TICK_DELAY);
}
@ -141,7 +135,7 @@ void cPiston::RetractPiston(int pistx, int pisty, int pistz)
m_World->BroadcastBlockAction(pistx, pisty, pistz, 1, pistonMeta & ~(8), pistonBlock);
m_World->BroadcastSoundEffect("tile.piston.in", pistx * 8, pisty * 8, pistz * 8, 0.5f, 0.7f);
m_World->QueueSetBlock(pistx, pisty, pistz, pistonBlock, pistonMeta & ~(8), PISTON_TICK_DELAY);
m_World->SetBlock(pistx, pisty, pistz, pistonBlock, pistonMeta & ~(8));
// Check the extension:
AddDir(pistx, pisty, pistz, pistonMeta, 1);
@ -199,15 +193,6 @@ bool cPiston::IsSticky(BLOCKTYPE a_BlockType)
bool cPiston::IsStickyExtension(NIBBLETYPE a_ExtMeta)
{
return ((a_ExtMeta & 0x08) != 0);
}
bool cPiston::CanPush(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta)
{
switch (a_BlockType)

View File

@ -63,9 +63,6 @@ public:
/// Returns true if the piston (with the specified meta) is extended
static bool IsExtended(NIBBLETYPE a_PistonMeta);
/// Returns true if the extension (with the specified meta) is sticky
static bool IsStickyExtension(NIBBLETYPE a_ExtMeta);
/// Returns true if the specified block can be pushed by a piston (and left intact)
static bool CanPush(BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta);

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,9 @@
#include "Simulator.h"
/// Per-chunk data for the simulator, specified individual chunks to simulate; 'Data' is not used
typedef cCoordWithIntList cRedstoneSimulatorChunkData;
@ -12,13 +15,13 @@ class cRedstoneSimulator :
{
typedef cSimulator super;
public:
cRedstoneSimulator(cWorld & a_World);
~cRedstoneSimulator();
virtual void Simulate( float a_Dt ) override;
virtual bool IsAllowedBlock( BLOCKTYPE a_BlockType ) override { return true; }
virtual void WakeUp(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override;
virtual void Simulate(float a_Dt) override {}; // Not used in this simulator
virtual void SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, cChunk * a_Chunk) override;
virtual bool IsAllowedBlock( BLOCKTYPE a_BlockType ) override { return IsRedstone(a_BlockType); }
enum eRedstoneDirection
{
@ -31,56 +34,166 @@ public:
eRedstoneDirection GetWireDirection(int a_BlockX, int a_BlockY, int a_BlockZ);
eRedstoneDirection GetWireDirection(const Vector3i & a_Pos) { return GetWireDirection(a_Pos.x, a_Pos.y, a_Pos.z); }
static bool IsRepeaterPointingTo (const Vector3i & a_RepeaterPos, char a_MetaData, const Vector3i & a_BlockPos);
static bool IsRepeaterPointingAway(const Vector3i & a_RepeaterPos, char a_MetaData, const Vector3i & a_BlockPos);
static NIBBLETYPE RepeaterRotationToMetaData(double a_Rotation);
static Vector3i GetRepeaterDirection(NIBBLETYPE a_MetaData);
static NIBBLETYPE LeverDirectionToMetaData(char a_Dir);
static bool IsLeverOn(cWorld * a_World, const Vector3i & a_BlockPos);
static bool IsLeverOn(NIBBLETYPE a_BlockMeta);
private:
struct sRepeaterChange
struct sPoweredBlocks // Define structure of the directly powered blocks list
{
Vector3i Position;
int Ticks;
bool bPowerOn;
bool bPowerOffNextTime;
Vector3i a_BlockPos; // Position of powered block
Vector3i a_SourcePos; // Position of source powering the block at a_BlockPos
BLOCKTYPE a_SourceBlock; // The source block type (for pistons pushing away sources and replacing with non source etc.)
};
typedef std::deque <Vector3i> BlockList;
typedef std::deque< sRepeaterChange > RepeaterList;
RepeaterList m_SetRepeaters;
struct sLinkedPoweredBlocks // Define structure of the indirectly powered blocks list (i.e. repeaters powering through a block to the block at the other side)
{
Vector3i a_BlockPos;
Vector3i a_MiddlePos;
Vector3i a_SourcePos;
BLOCKTYPE a_SourceBlock;
BLOCKTYPE a_MiddleBlock;
};
void SetRepeater(const Vector3i & a_Position, int a_Ticks, bool a_bPowerOn);
typedef std::vector <sPoweredBlocks> PoweredBlocksList;
typedef std::vector <sLinkedPoweredBlocks> LinkedBlocksList;
virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override {}
PoweredBlocksList m_PoweredBlocks;
LinkedBlocksList m_LinkedPoweredBlocks;
void HandleChange( const Vector3i & a_BlockPos );
BlockList RemoveCurrent( const Vector3i & a_BlockPos );
virtual void AddBlock(int a_BlockX, int a_BlockY, int a_BlockZ, cChunk * a_Chunk) override;
bool PowerBlock( const Vector3i & a_BlockPos, const Vector3i & a_FromBlock, char a_Power );
int UnPowerBlock( const Vector3i & a_BlockPos, const Vector3i & a_FromBlock );
// We want a_MyState for devices needing a full FastSetBlock (as opposed to meta) because with our simulation model, we cannot keep setting the block if it is already set correctly
// In addition to being non-performant, it would stop the player from actually breaking said device
bool IsPowered( const Vector3i & a_BlockPos, bool a_bOnlyByWire = false );
bool IsPowering( const Vector3i & a_PowerPos, const Vector3i & a_BlockPos, eRedstoneDirection a_WireDirection, bool a_bOnlyByWire );
BlockList m_Blocks;
BlockList m_BlocksBuffer;
/* ====== SOURCES ====== */
///<summary>Handles the redstone torch</summary>
void HandleRedstoneTorch(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyState);
///<summary>Handles the redstone block</summary>
void HandleRedstoneBlock(int a_BlockX, int a_BlockY, int a_BlockZ);
///<summary>Handles levers</summary>
void HandleRedstoneLever(int a_BlockX, int a_BlockY, int a_BlockZ);
///<summary>Handles buttons</summary>
void HandleRedstoneButton(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType);
/* ==================== */
BlockList m_RefreshPistons;
BlockList m_RefreshDropSpensers;
/* ====== CARRIERS ====== */
///<summary>Handles redstone wire</summary>
void HandleRedstoneWire(int a_BlockX, int a_BlockY, int a_BlockZ);
///<summary>Handles repeaters</summary>
void HandleRedstoneRepeater(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyState);
/* ====================== */
BlockList m_RefreshTorchesAround;
void RefreshTorchesAround( const Vector3i & a_BlockPos );
/* ====== DEVICES ====== */
///<summary>Handles pistons</summary>
void HandlePiston(int a_BlockX, int a_BlockY, int a_BlockZ);
///<summary>Handles dispensers and droppers</summary>
void HandleDropSpenser(int a_BlockX, int a_BlockY, int a_BlockZ);
///<summary>Handles TNT (exploding)</summary>
void HandleTNT(int a_BlockX, int a_BlockY, int a_BlockZ);
///<summary>Handles redstone lamps</summary>
void HandleRedstoneLamp(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyState);
///<summary>Handles doords</summary>
void HandleDoor(int a_BlockX, int a_BlockY, int a_BlockZ);
///<summary>Handles activator, detector, and powered rails</summary>
void HandleRail(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyType);
/* ===================== */
// TODO: The entire simulator is synchronized, no need to lock data structures; remove this
cCriticalSection m_CS;
};
/* ====== Helper functions ====== */
void SetBlockPowered(int a_BlockX, int a_BlockY, int a_BlockZ, int a_SourceX, int a_SourceY, int a_SourceZ, BLOCKTYPE a_SourceBlock);
void SetBlockLinkedPowered(int a_BlockX, int a_BlockY, int a_BlockZ, int a_MiddleX, int a_MiddleY, int a_MiddleZ, int a_SourceX, int a_SourceY, int a_SourceZ, BLOCKTYPE a_SourceBlock, BLOCKTYPE a_MiddeBlock);
void SetDirectionLinkedPowered(int a_BlockX, int a_BlockY, int a_BlockZ, char a_Direction, BLOCKTYPE a_SourceType);
bool AreCoordsPowered(int a_BlockX, int a_BlockY, int a_BlockZ);
bool IsRepeaterPowered(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta);
bool IsLeverOn(NIBBLETYPE a_BlockMeta);
bool IsButtonOn(NIBBLETYPE a_BlockMeta);
/* ============================== */
inline static bool IsMechanism(BLOCKTYPE Block)
{
switch (Block)
{
case E_BLOCK_PISTON:
case E_BLOCK_STICKY_PISTON:
case E_BLOCK_DISPENSER:
case E_BLOCK_DROPPER:
case E_BLOCK_TNT:
case E_BLOCK_REDSTONE_LAMP_OFF:
case E_BLOCK_REDSTONE_LAMP_ON:
case E_BLOCK_WOODEN_DOOR:
case E_BLOCK_IRON_DOOR:
case E_BLOCK_REDSTONE_REPEATER_OFF:
case E_BLOCK_REDSTONE_REPEATER_ON:
case E_BLOCK_POWERED_RAIL:
{
return true;
}
default: return false;
}
}
inline static bool IsPotentialSource(BLOCKTYPE Block)
{
switch (Block)
{
case E_BLOCK_WOODEN_BUTTON:
case E_BLOCK_STONE_BUTTON:
case E_BLOCK_REDSTONE_WIRE:
case E_BLOCK_REDSTONE_TORCH_OFF:
case E_BLOCK_REDSTONE_TORCH_ON:
case E_BLOCK_LEVER:
case E_BLOCK_REDSTONE_REPEATER_ON:
case E_BLOCK_REDSTONE_REPEATER_OFF:
case E_BLOCK_BLOCK_OF_REDSTONE:
case E_BLOCK_ACTIVE_COMPARATOR:
case E_BLOCK_INACTIVE_COMPARATOR:
{
return true;
}
default: return false;
}
}
inline static bool IsRedstone(BLOCKTYPE Block)
{
switch (Block)
{
// All redstone devices, please alpha sort
case E_BLOCK_ACTIVATOR_RAIL:
case E_BLOCK_ACTIVE_COMPARATOR:
case E_BLOCK_BLOCK_OF_REDSTONE:
case E_BLOCK_DETECTOR_RAIL:
case E_BLOCK_DISPENSER:
case E_BLOCK_DAYLIGHT_SENSOR:
case E_BLOCK_DROPPER:
case E_BLOCK_FENCE_GATE:
case E_BLOCK_HEAVY_WEIGHTED_PRESSURE_PLATE:
case E_BLOCK_HOPPER:
case E_BLOCK_INACTIVE_COMPARATOR:
case E_BLOCK_IRON_DOOR:
case E_BLOCK_LEVER:
case E_BLOCK_LIGHT_WEIGHTED_PRESSURE_PLATE:
case E_BLOCK_NOTE_BLOCK:
case E_BLOCK_REDSTONE_LAMP_OFF:
case E_BLOCK_REDSTONE_LAMP_ON:
case E_BLOCK_REDSTONE_REPEATER_OFF:
case E_BLOCK_REDSTONE_REPEATER_ON:
case E_BLOCK_REDSTONE_TORCH_OFF:
case E_BLOCK_REDSTONE_TORCH_ON:
case E_BLOCK_REDSTONE_WIRE:
case E_BLOCK_STICKY_PISTON:
case E_BLOCK_STONE_BUTTON:
case E_BLOCK_STONE_PRESSURE_PLATE:
case E_BLOCK_TNT:
case E_BLOCK_TRAPDOOR:
case E_BLOCK_TRIPWIRE_HOOK:
case E_BLOCK_WOODEN_BUTTON:
case E_BLOCK_WOODEN_DOOR:
case E_BLOCK_WOODEN_PRESSURE_PLATE:
case E_BLOCK_PISTON:
{
return true;
}
default: return false;
}
}
};