Merge pull request #461 from mc-server/repeaters
Repeaters, pressure plates, and others
This commit is contained in:
commit
e0e01d0615
@ -43,6 +43,40 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void OnPlaced(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType, NIBBLETYPE a_BlockMeta) override
|
||||||
|
{
|
||||||
|
super::OnPlaced(a_World, a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta);
|
||||||
|
|
||||||
|
// Alert diagonal rails
|
||||||
|
OnNeighborChanged(a_World, a_BlockX + 1, a_BlockY + 1, a_BlockZ);
|
||||||
|
OnNeighborChanged(a_World, a_BlockX - 1, a_BlockY + 1, a_BlockZ);
|
||||||
|
OnNeighborChanged(a_World, a_BlockX, a_BlockY + 1, a_BlockZ + 1);
|
||||||
|
OnNeighborChanged(a_World, a_BlockX, a_BlockY + 1, a_BlockZ - 1);
|
||||||
|
|
||||||
|
OnNeighborChanged(a_World, a_BlockX + 1, a_BlockY - 1, a_BlockZ);
|
||||||
|
OnNeighborChanged(a_World, a_BlockX - 1, a_BlockY - 1, a_BlockZ);
|
||||||
|
OnNeighborChanged(a_World, a_BlockX, a_BlockY - 1, a_BlockZ + 1);
|
||||||
|
OnNeighborChanged(a_World, a_BlockX, a_BlockY - 1, a_BlockZ - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
virtual void OnDestroyed(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override
|
||||||
|
{
|
||||||
|
super::OnDestroyed(a_World, a_BlockX, a_BlockY, a_BlockZ);
|
||||||
|
|
||||||
|
// Alert diagonal rails
|
||||||
|
OnNeighborChanged(a_World, a_BlockX + 1, a_BlockY + 1, a_BlockZ);
|
||||||
|
OnNeighborChanged(a_World, a_BlockX - 1, a_BlockY + 1, a_BlockZ);
|
||||||
|
OnNeighborChanged(a_World, a_BlockX, a_BlockY + 1, a_BlockZ + 1);
|
||||||
|
OnNeighborChanged(a_World, a_BlockX, a_BlockY + 1, a_BlockZ - 1);
|
||||||
|
|
||||||
|
OnNeighborChanged(a_World, a_BlockX + 1, a_BlockY - 1, a_BlockZ);
|
||||||
|
OnNeighborChanged(a_World, a_BlockX - 1, a_BlockY - 1, a_BlockZ);
|
||||||
|
OnNeighborChanged(a_World, a_BlockX, a_BlockY - 1, a_BlockZ + 1);
|
||||||
|
OnNeighborChanged(a_World, a_BlockX, a_BlockY - 1, a_BlockZ - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual void OnNeighborChanged(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override
|
virtual void OnNeighborChanged(cWorld *a_World, int a_BlockX, int a_BlockY, int a_BlockZ) override
|
||||||
{
|
{
|
||||||
NIBBLETYPE Meta = a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
|
NIBBLETYPE Meta = a_World->GetBlockMeta(a_BlockX, a_BlockY, a_BlockZ);
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "../Bindings/PluginManager.h"
|
#include "../Bindings/PluginManager.h"
|
||||||
#include "../Tracer.h"
|
#include "../Tracer.h"
|
||||||
#include "Minecart.h"
|
#include "Minecart.h"
|
||||||
|
#include "Player.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -239,10 +240,14 @@ void cEntity::TakeDamage(eDamageType a_DamageType, cEntity * a_Attacker, int a_R
|
|||||||
TDI.Attacker = a_Attacker;
|
TDI.Attacker = a_Attacker;
|
||||||
TDI.RawDamage = a_RawDamage;
|
TDI.RawDamage = a_RawDamage;
|
||||||
TDI.FinalDamage = a_FinalDamage;
|
TDI.FinalDamage = a_FinalDamage;
|
||||||
Vector3d Heading;
|
|
||||||
Heading.x = sin(GetRotation());
|
Vector3d Heading(0, 0, 0);
|
||||||
Heading.y = 0.4; // TODO: adjust the amount of "up" knockback when testing
|
if (a_Attacker != NULL)
|
||||||
Heading.z = cos(GetRotation());
|
{
|
||||||
|
Heading = a_Attacker->GetLookVector() * (a_Attacker->IsSprinting() ? 10 : 8);
|
||||||
|
}
|
||||||
|
Heading.y = 2;
|
||||||
|
|
||||||
TDI.Knockback = Heading * a_KnockbackAmount;
|
TDI.Knockback = Heading * a_KnockbackAmount;
|
||||||
DoTakeDamage(TDI);
|
DoTakeDamage(TDI);
|
||||||
}
|
}
|
||||||
@ -297,6 +302,16 @@ void cEntity::DoTakeDamage(TakeDamageInfo & a_TDI)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((a_TDI.Attacker != NULL) && (a_TDI.Attacker->IsPlayer()))
|
||||||
|
{
|
||||||
|
// IsOnGround() only is false if the player is moving downwards
|
||||||
|
if (!((cPlayer *)a_TDI.Attacker)->IsOnGround()) // TODO: Better damage increase, and check for enchantments (and use magic critical instead of plain)
|
||||||
|
{
|
||||||
|
a_TDI.FinalDamage += 2;
|
||||||
|
m_World->BroadcastEntityAnimation(*this, 4); // Critical hit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
m_Health -= (short)a_TDI.FinalDamage;
|
m_Health -= (short)a_TDI.FinalDamage;
|
||||||
|
|
||||||
// TODO: Apply damage to armor
|
// TODO: Apply damage to armor
|
||||||
@ -306,6 +321,8 @@ void cEntity::DoTakeDamage(TakeDamageInfo & a_TDI)
|
|||||||
m_Health = 0;
|
m_Health = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AddSpeed(a_TDI.Knockback * 2);
|
||||||
|
|
||||||
m_World->BroadcastEntityStatus(*this, ENTITY_STATUS_HURT);
|
m_World->BroadcastEntityStatus(*this, ENTITY_STATUS_HURT);
|
||||||
|
|
||||||
if (m_Health <= 0)
|
if (m_Health <= 0)
|
||||||
|
@ -252,6 +252,11 @@ void cPlayer::Tick(float a_Dt, cChunk & a_Chunk)
|
|||||||
m_World->SendPlayerList(this);
|
m_World->SendPlayerList(this);
|
||||||
m_LastPlayerListTime = t1.GetNowTime();
|
m_LastPlayerListTime = t1.GetNowTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (IsFlying())
|
||||||
|
{
|
||||||
|
m_LastGroundHeight = (float)GetPosY();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -452,11 +457,17 @@ void cPlayer::SetTouchGround(bool a_bTouchGround)
|
|||||||
if (m_LastJumpHeight > m_LastGroundHeight) Damage++;
|
if (m_LastJumpHeight > m_LastGroundHeight) Damage++;
|
||||||
m_LastJumpHeight = (float)GetPosY();
|
m_LastJumpHeight = (float)GetPosY();
|
||||||
|
|
||||||
if ((Damage > 0) && (!IsGameModeCreative()))
|
if (Damage > 0)
|
||||||
|
{
|
||||||
|
if (!IsGameModeCreative())
|
||||||
{
|
{
|
||||||
TakeDamage(dtFalling, NULL, Damage, Damage, 0);
|
TakeDamage(dtFalling, NULL, Damage, Damage, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mojang uses floor() to get X and Z positions, instead of just casting it to an (int)
|
||||||
|
GetWorld()->BroadcastSoundParticleEffect(2006, (int)floor(GetPosX()), (int)GetPosY() - 1, (int)floor(GetPosZ()), Damage /* Used as particle effect speed modifier */);
|
||||||
|
}
|
||||||
|
|
||||||
m_LastGroundHeight = (float)GetPosY();
|
m_LastGroundHeight = (float)GetPosY();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -979,6 +990,12 @@ void cPlayer::SetGameMode(eGameMode a_GameMode)
|
|||||||
|
|
||||||
m_GameMode = a_GameMode;
|
m_GameMode = a_GameMode;
|
||||||
m_ClientHandle->SendGameMode(a_GameMode);
|
m_ClientHandle->SendGameMode(a_GameMode);
|
||||||
|
|
||||||
|
if (!IsGameModeCreative())
|
||||||
|
{
|
||||||
|
SetFlying(false);
|
||||||
|
SetCanFly(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
32
src/Root.cpp
32
src/Root.cpp
@ -22,6 +22,7 @@
|
|||||||
#include "inifile/iniFile.h"
|
#include "inifile/iniFile.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
#include "conio.h"
|
||||||
#include <psapi.h>
|
#include <psapi.h>
|
||||||
#elif defined(__linux__)
|
#elif defined(__linux__)
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
@ -29,6 +30,8 @@
|
|||||||
#include <mach/mach.h>
|
#include <mach/mach.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
extern bool g_TERMINATE_EVENT_RAISED;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -76,7 +79,7 @@ void cRoot::InputThread(void * a_Params)
|
|||||||
|
|
||||||
cLogCommandOutputCallback Output;
|
cLogCommandOutputCallback Output;
|
||||||
|
|
||||||
while (!(self.m_bStop || self.m_bRestart) && std::cin.good())
|
while (!self.m_bStop && !self.m_bRestart && !g_TERMINATE_EVENT_RAISED && std::cin.good())
|
||||||
{
|
{
|
||||||
AString Command;
|
AString Command;
|
||||||
std::getline(std::cin, Command);
|
std::getline(std::cin, Command);
|
||||||
@ -86,9 +89,9 @@ void cRoot::InputThread(void * a_Params)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(self.m_bStop || self.m_bRestart))
|
if (g_TERMINATE_EVENT_RAISED || !std::cin.good())
|
||||||
{
|
{
|
||||||
// We have come here because the std::cin has received an EOF and the server is still running; stop the server:
|
// We have come here because the std::cin has received an EOF / a terminate signal has been sent, and the server is still running; stop the server:
|
||||||
self.m_bStop = true;
|
self.m_bStop = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -99,6 +102,12 @@ void cRoot::InputThread(void * a_Params)
|
|||||||
|
|
||||||
void cRoot::Start(void)
|
void cRoot::Start(void)
|
||||||
{
|
{
|
||||||
|
#ifdef _WIN32
|
||||||
|
HWND hwnd = GetConsoleWindow();
|
||||||
|
HMENU hmenu = GetSystemMenu(hwnd, FALSE);
|
||||||
|
EnableMenuItem(hmenu, SC_CLOSE, MF_GRAYED); // Disable close button when starting up; it causes problems with our CTRL-CLOSE handling
|
||||||
|
#endif
|
||||||
|
|
||||||
cDeadlockDetect dd;
|
cDeadlockDetect dd;
|
||||||
delete m_Log;
|
delete m_Log;
|
||||||
m_Log = new cMCLogger();
|
m_Log = new cMCLogger();
|
||||||
@ -192,12 +201,20 @@ void cRoot::Start(void)
|
|||||||
finishmseconds -= mseconds;
|
finishmseconds -= mseconds;
|
||||||
|
|
||||||
LOG("Startup complete, took %i ms!", finishmseconds);
|
LOG("Startup complete, took %i ms!", finishmseconds);
|
||||||
|
#ifdef _WIN32
|
||||||
|
EnableMenuItem(hmenu, SC_CLOSE, MF_ENABLED); // Re-enable close button
|
||||||
|
#endif
|
||||||
|
|
||||||
while (!m_bStop && !m_bRestart) // These are modified by external threads
|
while (!m_bStop && !m_bRestart && !g_TERMINATE_EVENT_RAISED) // These are modified by external threads
|
||||||
{
|
{
|
||||||
cSleep::MilliSleep(1000);
|
cSleep::MilliSleep(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (g_TERMINATE_EVENT_RAISED)
|
||||||
|
{
|
||||||
|
m_bStop = true;
|
||||||
|
}
|
||||||
|
|
||||||
#if !defined(ANDROID_NDK)
|
#if !defined(ANDROID_NDK)
|
||||||
delete m_InputThread; m_InputThread = NULL;
|
delete m_InputThread; m_InputThread = NULL;
|
||||||
#endif
|
#endif
|
||||||
@ -222,7 +239,7 @@ void cRoot::Start(void)
|
|||||||
delete m_FurnaceRecipe; m_FurnaceRecipe = NULL;
|
delete m_FurnaceRecipe; m_FurnaceRecipe = NULL;
|
||||||
delete m_CraftingRecipes; m_CraftingRecipes = NULL;
|
delete m_CraftingRecipes; m_CraftingRecipes = NULL;
|
||||||
LOGD("Forgetting groups...");
|
LOGD("Forgetting groups...");
|
||||||
delete m_GroupManager; m_GroupManager = 0;
|
delete m_GroupManager; m_GroupManager = NULL;
|
||||||
LOGD("Unloading worlds...");
|
LOGD("Unloading worlds...");
|
||||||
UnloadWorlds();
|
UnloadWorlds();
|
||||||
|
|
||||||
@ -233,12 +250,11 @@ void cRoot::Start(void)
|
|||||||
cBlockHandler::Deinit();
|
cBlockHandler::Deinit();
|
||||||
|
|
||||||
LOG("Cleaning up...");
|
LOG("Cleaning up...");
|
||||||
//delete HeartBeat; HeartBeat = 0;
|
delete m_Server; m_Server = NULL;
|
||||||
delete m_Server; m_Server = 0;
|
|
||||||
LOG("Shutdown successful!");
|
LOG("Shutdown successful!");
|
||||||
}
|
}
|
||||||
|
|
||||||
delete m_Log; m_Log = 0;
|
delete m_Log; m_Log = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include "../Blocks/BlockTorch.h"
|
#include "../Blocks/BlockTorch.h"
|
||||||
#include "../Blocks/BlockDoor.h"
|
#include "../Blocks/BlockDoor.h"
|
||||||
#include "../Piston.h"
|
#include "../Piston.h"
|
||||||
|
#include "../Tracer.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -106,21 +107,47 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c
|
|||||||
((SourceBlockType == E_BLOCK_REDSTONE_WIRE) && (SourceBlockMeta == 0)) ||
|
((SourceBlockType == E_BLOCK_REDSTONE_WIRE) && (SourceBlockMeta == 0)) ||
|
||||||
((SourceBlockType == E_BLOCK_LEVER) && !IsLeverOn(SourceBlockMeta)) ||
|
((SourceBlockType == E_BLOCK_LEVER) && !IsLeverOn(SourceBlockMeta)) ||
|
||||||
((SourceBlockType == E_BLOCK_DETECTOR_RAIL) && (SourceBlockMeta & 0x08) == 0x08) ||
|
((SourceBlockType == E_BLOCK_DETECTOR_RAIL) && (SourceBlockMeta & 0x08) == 0x08) ||
|
||||||
(((SourceBlockType == E_BLOCK_STONE_BUTTON) || (SourceBlockType == E_BLOCK_WOODEN_BUTTON)) && (!IsButtonOn(SourceBlockMeta)))
|
(((SourceBlockType == E_BLOCK_STONE_BUTTON) || (SourceBlockType == E_BLOCK_WOODEN_BUTTON)) && (!IsButtonOn(SourceBlockMeta))) ||
|
||||||
|
(((SourceBlockType == E_BLOCK_STONE_PRESSURE_PLATE) || (SourceBlockType == E_BLOCK_WOODEN_PRESSURE_PLATE)) && (SourceBlockMeta == 0))
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
LOGD("cRedstoneSimulator: Erased block %s from powered blocks list due to present/past metadata mismatch", ItemToFullString(itr->a_SourceBlock).c_str());
|
LOGD("cRedstoneSimulator: Erased block %s from powered blocks list due to present/past metadata mismatch", ItemToFullString(itr->a_SourceBlock).c_str());
|
||||||
itr = m_PoweredBlocks.erase(itr);
|
itr = m_PoweredBlocks.erase(itr);
|
||||||
}
|
}
|
||||||
else if ((SourceBlockType == E_BLOCK_REDSTONE_WIRE) && (DestBlockType == E_BLOCK_REDSTONE_WIRE))
|
else if (SourceBlockType == E_BLOCK_DAYLIGHT_SENSOR)
|
||||||
{
|
{
|
||||||
// It is simply not allowed that a wire powers another wire, presuming that data here is sane and a dest and source are beside each other
|
if (!a_Chunk->IsLightValid())
|
||||||
LOGD("cRedstoneSimulator: Erased redstone wire from powered blocks list because it's source was also wire");
|
{
|
||||||
|
m_World.QueueLightChunk(a_ChunkX, a_ChunkZ);
|
||||||
|
++itr;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NIBBLETYPE SkyLight;
|
||||||
|
a_Chunk->UnboundedRelGetBlockSkyLight(RelX, itr->a_SourcePos.y + 1, RelZ, SkyLight);
|
||||||
|
|
||||||
|
if (a_Chunk->GetTimeAlteredLight(SkyLight) <= 8) // Could use SkyLight - m_World.GetSkyDarkness();
|
||||||
|
{
|
||||||
|
LOGD("cRedstoneSimulator: Erased daylight sensor from powered blocks list due to insufficient light level");
|
||||||
itr = m_PoweredBlocks.erase(itr);
|
itr = m_PoweredBlocks.erase(itr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
itr++;
|
++itr;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ((SourceBlockType == E_BLOCK_REDSTONE_WIRE) && (DestBlockType == E_BLOCK_REDSTONE_WIRE))
|
||||||
|
{
|
||||||
|
// It is simply not allowed that a wire powers another wire, presuming that data here is sane and a dest and source are beside each other
|
||||||
|
LOGD("cRedstoneSimulator: Erased redstone wire from powered blocks list because its source was also wire");
|
||||||
|
itr = m_PoweredBlocks.erase(itr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++itr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -165,7 +192,7 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
itr++;
|
++itr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,7 +213,7 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
itr++;
|
++itr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,12 +233,8 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c
|
|||||||
itr = m_RepeatersDelayList.erase(itr);
|
itr = m_RepeatersDelayList.erase(itr);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (itr->a_ElapsedTicks < itr->a_DelayTicks)
|
|
||||||
{
|
|
||||||
itr->a_ElapsedTicks++;
|
|
||||||
}
|
|
||||||
|
|
||||||
itr++;
|
++itr;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (cRedstoneSimulatorChunkData::iterator dataitr = ChunkData.begin(), end = ChunkData.end(); dataitr != end;)
|
for (cRedstoneSimulatorChunkData::iterator dataitr = ChunkData.begin(), end = ChunkData.end(); dataitr != end;)
|
||||||
@ -285,6 +308,12 @@ void cRedstoneSimulator::SimulateChunk(float a_Dt, int a_ChunkX, int a_ChunkZ, c
|
|||||||
HandleRail(a_X, dataitr->y, a_Z, BlockType);
|
HandleRail(a_X, dataitr->y, a_Z, BlockType);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case E_BLOCK_WOODEN_PRESSURE_PLATE:
|
||||||
|
case E_BLOCK_STONE_PRESSURE_PLATE:
|
||||||
|
{
|
||||||
|
HandlePressurePlate(a_X, dataitr->y, a_Z, BlockType);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
++dataitr;
|
++dataitr;
|
||||||
@ -601,7 +630,7 @@ void cRedstoneSimulator::HandleRedstoneRepeater(int a_BlockX, int a_BlockY, int
|
|||||||
QueueRepeaterPowerChange(a_BlockX, a_BlockY, a_BlockZ, a_Meta, 0, false);
|
QueueRepeaterPowerChange(a_BlockX, a_BlockY, a_BlockZ, a_Meta, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (RepeatersDelayList::iterator itr = m_RepeatersDelayList.begin(); itr != m_RepeatersDelayList.end(); itr++)
|
for (RepeatersDelayList::iterator itr = m_RepeatersDelayList.begin(); itr != m_RepeatersDelayList.end(); ++itr)
|
||||||
{
|
{
|
||||||
if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
|
if (!itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
|
||||||
{
|
{
|
||||||
@ -659,8 +688,14 @@ void cRedstoneSimulator::HandleRedstoneRepeater(int a_BlockX, int a_BlockY, int
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
// Tick incrementing handled in SimChunk
|
{
|
||||||
|
// Apparently, incrementing ticks only works reliably here, and not in SimChunk;
|
||||||
|
// With a world with lots of redstone, the repeaters simply do not delay
|
||||||
|
// I am confounded to say why. Perhaps optimisation failure.
|
||||||
|
LOGD("Incremented a repeater @ %i %i %i | Elapsed ticks: %i | Target delay: %i", itr->a_BlockPos.x, itr->a_BlockPos.y, itr->a_BlockPos.z, itr->a_ElapsedTicks, itr->a_DelayTicks);
|
||||||
|
itr->a_ElapsedTicks++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -897,11 +932,114 @@ void cRedstoneSimulator::HandleNoteBlock(int a_BlockX, int a_BlockY, int a_Block
|
|||||||
|
|
||||||
void cRedstoneSimulator::HandleDaylightSensor(int a_BlockX, int a_BlockY, int a_BlockZ)
|
void cRedstoneSimulator::HandleDaylightSensor(int a_BlockX, int a_BlockY, int a_BlockZ)
|
||||||
{
|
{
|
||||||
if (m_World.GetBlockSkyLight(a_BlockX, a_BlockY + 1, a_BlockZ) > 10)
|
int a_ChunkX, a_ChunkZ;
|
||||||
|
cChunkDef::BlockToChunk(a_BlockX, a_BlockZ, a_ChunkX, a_ChunkZ);
|
||||||
|
|
||||||
|
if (!m_World.IsChunkLighted(a_ChunkX, a_ChunkZ))
|
||||||
|
{
|
||||||
|
m_World.QueueLightChunk(a_ChunkX, a_ChunkZ);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NIBBLETYPE SkyLight = m_World.GetBlockSkyLight(a_BlockX, a_BlockY + 1, a_BlockZ) - m_World.GetSkyDarkness();
|
||||||
|
if (SkyLight > 8)
|
||||||
{
|
{
|
||||||
SetAllDirsAsPowered(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_DAYLIGHT_SENSOR);
|
SetAllDirsAsPowered(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_DAYLIGHT_SENSOR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void cRedstoneSimulator::HandlePressurePlate(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyType)
|
||||||
|
{
|
||||||
|
switch (a_MyType)
|
||||||
|
{
|
||||||
|
case E_BLOCK_STONE_PRESSURE_PLATE:
|
||||||
|
{
|
||||||
|
// MCS feature - stone pressure plates can only be triggered by players :D
|
||||||
|
cPlayer * a_Player = m_World.FindClosestPlayer(Vector3f(a_BlockX + 0.5f, (float)a_BlockY, a_BlockZ + 0.5f), 0.5f);
|
||||||
|
|
||||||
|
if (a_Player != NULL)
|
||||||
|
{
|
||||||
|
m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, 0x1);
|
||||||
|
SetAllDirsAsPowered(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_STONE_PRESSURE_PLATE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, 0x0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case E_BLOCK_WOODEN_PRESSURE_PLATE:
|
||||||
|
{
|
||||||
|
class cWoodenPressurePlateCallback :
|
||||||
|
public cEntityCallback
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
cWoodenPressurePlateCallback(int a_BlockX, int a_BlockY, int a_BlockZ, cWorld * a_World) :
|
||||||
|
m_X(a_BlockX),
|
||||||
|
m_Y(a_BlockY),
|
||||||
|
m_Z(a_BlockZ),
|
||||||
|
m_World(a_World),
|
||||||
|
m_Entity(NULL)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool Item(cEntity * a_Entity) override
|
||||||
|
{
|
||||||
|
cTracer LineOfSight(m_World);
|
||||||
|
|
||||||
|
Vector3f EntityPos = a_Entity->GetPosition();
|
||||||
|
Vector3f BlockPos(m_X + 0.5f, (float)m_Y, m_Z + 0.5f);
|
||||||
|
float Distance = (EntityPos - BlockPos).Length();
|
||||||
|
|
||||||
|
if (Distance < 0.5)
|
||||||
|
{
|
||||||
|
if (!LineOfSight.Trace(BlockPos, (EntityPos - BlockPos), (int)(EntityPos - BlockPos).Length()))
|
||||||
|
{
|
||||||
|
m_Entity = a_Entity;
|
||||||
|
return true; // Break out, we only need to know for wooden plates that at least one entity is on top
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FoundEntity(void) const
|
||||||
|
{
|
||||||
|
return m_Entity != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
cEntity * m_Entity;
|
||||||
|
cWorld * m_World;
|
||||||
|
|
||||||
|
int m_X;
|
||||||
|
int m_Y;
|
||||||
|
int m_Z;
|
||||||
|
} ;
|
||||||
|
|
||||||
|
cWoodenPressurePlateCallback WoodenPressurePlateCallback(a_BlockX, a_BlockY, a_BlockZ, &m_World);
|
||||||
|
m_World.ForEachEntity(WoodenPressurePlateCallback);
|
||||||
|
|
||||||
|
if (WoodenPressurePlateCallback.FoundEntity())
|
||||||
|
{
|
||||||
|
m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, 0x1);
|
||||||
|
SetAllDirsAsPowered(a_BlockX, a_BlockY, a_BlockZ, E_BLOCK_WOODEN_PRESSURE_PLATE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_World.SetBlockMeta(a_BlockX, a_BlockY, a_BlockZ, 0x0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
LOGD("Unimplemented pressure plate type %s in cRedstoneSimulator", ItemToFullString(a_MyType).c_str());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1308,7 +1446,7 @@ void cRedstoneSimulator::SetPlayerToggleableBlockAsSimulated(int a_BlockX, int a
|
|||||||
|
|
||||||
void cRedstoneSimulator::QueueRepeaterPowerChange(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta, short a_ElapsedTicks, bool ShouldPowerOn)
|
void cRedstoneSimulator::QueueRepeaterPowerChange(int a_BlockX, int a_BlockY, int a_BlockZ, NIBBLETYPE a_Meta, short a_ElapsedTicks, bool ShouldPowerOn)
|
||||||
{
|
{
|
||||||
for (RepeatersDelayList::iterator itr = m_RepeatersDelayList.begin(); itr != m_RepeatersDelayList.end(); itr++)
|
for (RepeatersDelayList::iterator itr = m_RepeatersDelayList.begin(); itr != m_RepeatersDelayList.end(); ++itr)
|
||||||
{
|
{
|
||||||
if (itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
|
if (itr->a_BlockPos.Equals(Vector3i(a_BlockX, a_BlockY, a_BlockZ)))
|
||||||
{
|
{
|
||||||
@ -1318,7 +1456,7 @@ void cRedstoneSimulator::QueueRepeaterPowerChange(int a_BlockX, int a_BlockY, in
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Already in here (normal to allow repeater to continue on powering and updating blocks in front) - just update info and quit
|
// Already in here (normal to allow repeater to continue on powering and updating blocks in front) - just update info and quit
|
||||||
itr->a_DelayTicks = (((a_Meta & 0xC) >> 0x2) + 1) * 2; // See below for description
|
itr->a_DelayTicks = (((a_Meta & 0xC) >> 0x2) + (ShouldPowerOn ? 1 : 0)) * 2; // See below for description
|
||||||
itr->a_ElapsedTicks = 0;
|
itr->a_ElapsedTicks = 0;
|
||||||
itr->ShouldPowerOn = ShouldPowerOn;
|
itr->ShouldPowerOn = ShouldPowerOn;
|
||||||
return;
|
return;
|
||||||
@ -1331,7 +1469,8 @@ void cRedstoneSimulator::QueueRepeaterPowerChange(int a_BlockX, int a_BlockY, in
|
|||||||
|
|
||||||
// Gets the top two bits (delay time), shifts them into the lower two bits, and adds one (meta 0 = 1 tick; 1 = 2 etc.)
|
// Gets the top two bits (delay time), shifts them into the lower two bits, and adds one (meta 0 = 1 tick; 1 = 2 etc.)
|
||||||
// * 2 because apparently, MCS ticks are way faster than vanilla ticks, so repeater aren't noticeably delayed
|
// * 2 because apparently, MCS ticks are way faster than vanilla ticks, so repeater aren't noticeably delayed
|
||||||
RC.a_DelayTicks = (((a_Meta & 0xC) >> 0x2) + 1) * 2;
|
// We don't +1 when powering off because everything seems to already delay a tick when powering off, why? No idea :P
|
||||||
|
RC.a_DelayTicks = (((a_Meta & 0xC) >> 0x2) + (ShouldPowerOn ? 1 : 0)) * 2;
|
||||||
|
|
||||||
|
|
||||||
RC.a_ElapsedTicks = 0;
|
RC.a_ElapsedTicks = 0;
|
||||||
|
@ -89,6 +89,10 @@ private:
|
|||||||
void HandleRedstoneLever(int a_BlockX, int a_BlockY, int a_BlockZ);
|
void HandleRedstoneLever(int a_BlockX, int a_BlockY, int a_BlockZ);
|
||||||
/// <summary>Handles buttons</summary>
|
/// <summary>Handles buttons</summary>
|
||||||
void HandleRedstoneButton(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType);
|
void HandleRedstoneButton(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_BlockType);
|
||||||
|
/// <summary>Handles daylight sensors</summary>
|
||||||
|
void HandleDaylightSensor(int a_BlockX, int a_BlockY, int a_BlockZ);
|
||||||
|
/// <summary>Handles pressure plates</summary>
|
||||||
|
void HandlePressurePlate(int a_BlockX, int a_BlockY, int a_BlockZ, BLOCKTYPE a_MyType);
|
||||||
/* ==================== */
|
/* ==================== */
|
||||||
|
|
||||||
/* ====== CARRIERS ====== */
|
/* ====== CARRIERS ====== */
|
||||||
@ -115,8 +119,6 @@ private:
|
|||||||
void HandleTrapdoor(int a_BlockX, int a_BlockY, int a_BlockZ);
|
void HandleTrapdoor(int a_BlockX, int a_BlockY, int a_BlockZ);
|
||||||
/// <summary>Handles noteblocks</summary>
|
/// <summary>Handles noteblocks</summary>
|
||||||
void HandleNoteBlock(int a_BlockX, int a_BlockY, int a_BlockZ);
|
void HandleNoteBlock(int a_BlockX, int a_BlockY, int a_BlockZ);
|
||||||
/// <summary>Handles noteblocks</summary>
|
|
||||||
void HandleDaylightSensor(int a_BlockX, int a_BlockY, int a_BlockZ);
|
|
||||||
/* ===================== */
|
/* ===================== */
|
||||||
|
|
||||||
/* ====== Helper functions ====== */
|
/* ====== Helper functions ====== */
|
||||||
|
60
src/main.cpp
60
src/main.cpp
@ -11,6 +11,10 @@
|
|||||||
#include <dbghelp.h>
|
#include <dbghelp.h>
|
||||||
#endif // _MSC_VER
|
#endif // _MSC_VER
|
||||||
|
|
||||||
|
// Here, we have some ALL CAPS variables, to give the impression that this is deeeep, gritty programming :P
|
||||||
|
bool g_TERMINATE_EVENT_RAISED = false; // If something has told the server to stop; checked periodically in cRoot
|
||||||
|
bool g_SERVER_TERMINATED = false; // Set to true when the server terminates, so our CTRL handler can then tell Windows to close the console
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -33,14 +37,21 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void NonCtrlHandler(int a_Signal)
|
||||||
|
{
|
||||||
|
LOGD("Terminate event raised from std::signal");
|
||||||
|
g_TERMINATE_EVENT_RAISED = true;
|
||||||
|
|
||||||
void ShowCrashReport(int)
|
switch (a_Signal)
|
||||||
|
{
|
||||||
|
case SIGSEGV:
|
||||||
{
|
{
|
||||||
std::signal(SIGSEGV, SIG_DFL);
|
std::signal(SIGSEGV, SIG_DFL);
|
||||||
|
LOGWARN("Segmentation fault; MCServer has crashed :(");
|
||||||
printf("\n\nMCServer has crashed!\n");
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
exit(-1);
|
default: break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -111,13 +122,33 @@ LONG WINAPI LastChanceExceptionFilter(__in struct _EXCEPTION_POINTERS * a_Except
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
// Handle CTRL events in windows, including console window close
|
||||||
|
BOOL CtrlHandler(DWORD fdwCtrlType)
|
||||||
|
{
|
||||||
|
g_TERMINATE_EVENT_RAISED = true;
|
||||||
|
LOGD("Terminate event raised from the Windows CtrlHandler");
|
||||||
|
|
||||||
|
if (fdwCtrlType == CTRL_CLOSE_EVENT) // Console window closed via 'x' button, Windows will try to close immediately, therefore...
|
||||||
|
{
|
||||||
|
while (!g_SERVER_TERMINATED) { cSleep::MilliSleep(100); } // Delay as much as possible to try to get the server to shut down cleanly
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// main:
|
// main:
|
||||||
|
|
||||||
int main( int argc, char **argv )
|
int main( int argc, char **argv )
|
||||||
{
|
{
|
||||||
(void)argc;
|
UNUSED(argc);
|
||||||
(void)argv;
|
UNUSED(argv);
|
||||||
|
|
||||||
#if defined(_MSC_VER) && defined(_DEBUG) && defined(ENABLE_LEAK_FINDER)
|
#if defined(_MSC_VER) && defined(_DEBUG) && defined(ENABLE_LEAK_FINDER)
|
||||||
InitLeakFinder();
|
InitLeakFinder();
|
||||||
@ -150,6 +181,13 @@ int main( int argc, char **argv )
|
|||||||
#endif // _WIN32 && !_WIN64
|
#endif // _WIN32 && !_WIN64
|
||||||
// End of dump-file magic
|
// End of dump-file magic
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
if (!SetConsoleCtrlHandler((PHANDLER_ROUTINE)CtrlHandler, TRUE))
|
||||||
|
{
|
||||||
|
LOGERROR("Could not install the Windows CTRL handler!");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(_DEBUG) && defined(_MSC_VER)
|
#if defined(_DEBUG) && defined(_MSC_VER)
|
||||||
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
|
_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
|
||||||
|
|
||||||
@ -160,7 +198,9 @@ int main( int argc, char **argv )
|
|||||||
#endif // _DEBUG && _MSC_VER
|
#endif // _DEBUG && _MSC_VER
|
||||||
|
|
||||||
#ifndef _DEBUG
|
#ifndef _DEBUG
|
||||||
std::signal(SIGSEGV, ShowCrashReport);
|
std::signal(SIGSEGV, NonCtrlHandler);
|
||||||
|
std::signal(SIGTERM, NonCtrlHandler);
|
||||||
|
std::signal(SIGINT, NonCtrlHandler);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// DEBUG: test the dumpfile creation:
|
// DEBUG: test the dumpfile creation:
|
||||||
@ -189,7 +229,9 @@ int main( int argc, char **argv )
|
|||||||
DeinitLeakFinder();
|
DeinitLeakFinder();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
g_SERVER_TERMINATED = true;
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user