mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-09 17:48:19 +00:00
Merge #6150
6150: Recreate all entities when restarting round, fix server crash on maps with more than 64 spawn points of same type r=def- a=Robyt3 ## Checklist - [X] Tested the change ingame - [ ] Provided screenshots if it is a visual change - [ ] Tested in combination with possibly related configuration options - [ ] Written a unit test (especially base/) or added coverage to integration test - [ ] Considered possible null pointers and out of bounds array indexing - [X] Changed no physics that affect existing maps - [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional) Co-authored-by: Robert Müller <robytemueller@gmail.com>
This commit is contained in:
commit
f51dd365e4
|
@ -40,6 +40,11 @@ void CDoor::ResetCollision()
|
|||
}
|
||||
}
|
||||
|
||||
void CDoor::Reset()
|
||||
{
|
||||
m_MarkedForDestroy = true;
|
||||
}
|
||||
|
||||
void CDoor::Snap(int SnappingClient)
|
||||
{
|
||||
if(NetworkClipped(SnappingClient, m_Pos) && NetworkClipped(SnappingClient, m_To))
|
||||
|
|
|
@ -17,6 +17,7 @@ public:
|
|||
CDoor(CGameWorld *pGameWorld, vec2 Pos, float Rotation, int Length,
|
||||
int Number);
|
||||
|
||||
void Reset() override;
|
||||
void Snap(int SnappingClient) override;
|
||||
};
|
||||
|
||||
|
|
|
@ -21,13 +21,12 @@ CPickup::CPickup(CGameWorld *pGameWorld, int Type, int SubType, int Layer, int N
|
|||
m_Layer = Layer;
|
||||
m_Number = Number;
|
||||
|
||||
Reset();
|
||||
|
||||
GameWorld()->InsertEntity(this);
|
||||
}
|
||||
|
||||
void CPickup::Reset()
|
||||
{
|
||||
m_MarkedForDestroy = true;
|
||||
}
|
||||
|
||||
void CPickup::Tick()
|
||||
|
|
|
@ -51,8 +51,7 @@ CProjectile::CProjectile(
|
|||
|
||||
void CProjectile::Reset()
|
||||
{
|
||||
if(m_LifeSpan > -2)
|
||||
m_MarkedForDestroy = true;
|
||||
m_MarkedForDestroy = true;
|
||||
}
|
||||
|
||||
vec2 CProjectile::GetPos(float Time)
|
||||
|
|
|
@ -1547,7 +1547,6 @@ void CGameContext::OnClientDrop(int ClientID, const char *pReason)
|
|||
delete m_apPlayers[ClientID];
|
||||
m_apPlayers[ClientID] = 0;
|
||||
|
||||
//(void)m_pController->CheckTeamBalance();
|
||||
m_VoteUpdate = true;
|
||||
|
||||
// update spectator modes
|
||||
|
@ -2046,7 +2045,6 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID)
|
|||
m_apPlayers[ClientID]->m_Last_KickVote = time_get();
|
||||
return;
|
||||
}
|
||||
//else if(!g_Config.m_SvVoteKick)
|
||||
else if(!g_Config.m_SvVoteKick && !Authed) // allow admins to call kick votes even if they are forbidden
|
||||
{
|
||||
SendChatTarget(ClientID, "Server does not allow voting to kick players");
|
||||
|
@ -3242,7 +3240,7 @@ void CGameContext::OnConsoleInit()
|
|||
#include <game/ddracechat.h>
|
||||
}
|
||||
|
||||
void CGameContext::OnInit(/*class IKernel *pKernel*/)
|
||||
void CGameContext::OnInit()
|
||||
{
|
||||
m_pServer = Kernel()->RequestInterface<IServer>();
|
||||
m_pConfig = Kernel()->RequestInterface<IConfigManager>()->Values();
|
||||
|
@ -3264,9 +3262,6 @@ void CGameContext::OnInit(/*class IKernel *pKernel*/)
|
|||
|
||||
DeleteTempfile();
|
||||
|
||||
//if(!data) // only load once
|
||||
//data = load_data_from_memory(internal_data);
|
||||
|
||||
for(int i = 0; i < NUM_NETOBJTYPES; i++)
|
||||
Server()->SnapSetStaticsize(i, m_NetObjHandler.GetObjSize(i));
|
||||
|
||||
|
@ -3281,10 +3276,6 @@ void CGameContext::OnInit(/*class IKernel *pKernel*/)
|
|||
Server()->GetMapInfo(aMapName, sizeof(aMapName), &MapSize, &MapSha256, &MapCrc);
|
||||
m_MapBugs = GetMapBugs(aMapName, MapSize, MapSha256);
|
||||
|
||||
// reset everything here
|
||||
//world = new GAMEWORLD;
|
||||
//players = new CPlayer[MAX_CLIENTS];
|
||||
|
||||
// Reset Tunezones
|
||||
CTuningParams TuningParams;
|
||||
for(int i = 0; i < NUM_TUNEZONES; i++)
|
||||
|
@ -3440,108 +3431,8 @@ void CGameContext::OnInit(/*class IKernel *pKernel*/)
|
|||
m_pScore = new CScore(this, ((CServer *)Server())->DbPool());
|
||||
}
|
||||
|
||||
// setup core world
|
||||
//for(int i = 0; i < MAX_CLIENTS; i++)
|
||||
// game.players[i].core.world = &game.world.core;
|
||||
|
||||
// create all entities from the game layer
|
||||
CMapItemLayerTilemap *pTileMap = m_Layers.GameLayer();
|
||||
CTile *pTiles = (CTile *)Kernel()->RequestInterface<IMap>()->GetData(pTileMap->m_Data);
|
||||
|
||||
CTile *pFront = 0;
|
||||
CSwitchTile *pSwitch = 0;
|
||||
if(m_Layers.FrontLayer())
|
||||
pFront = (CTile *)Kernel()->RequestInterface<IMap>()->GetData(m_Layers.FrontLayer()->m_Front);
|
||||
if(m_Layers.SwitchLayer())
|
||||
pSwitch = (CSwitchTile *)Kernel()->RequestInterface<IMap>()->GetData(m_Layers.SwitchLayer()->m_Switch);
|
||||
|
||||
for(int y = 0; y < pTileMap->m_Height; y++)
|
||||
{
|
||||
for(int x = 0; x < pTileMap->m_Width; x++)
|
||||
{
|
||||
int Index = pTiles[y * pTileMap->m_Width + x].m_Index;
|
||||
|
||||
if(Index == TILE_OLDLASER)
|
||||
{
|
||||
g_Config.m_SvOldLaser = 1;
|
||||
dbg_msg("game_layer", "found old laser tile");
|
||||
}
|
||||
else if(Index == TILE_NPC)
|
||||
{
|
||||
m_Tuning.Set("player_collision", 0);
|
||||
dbg_msg("game_layer", "found no collision tile");
|
||||
}
|
||||
else if(Index == TILE_EHOOK)
|
||||
{
|
||||
g_Config.m_SvEndlessDrag = 1;
|
||||
dbg_msg("game_layer", "found unlimited hook time tile");
|
||||
}
|
||||
else if(Index == TILE_NOHIT)
|
||||
{
|
||||
g_Config.m_SvHit = 0;
|
||||
dbg_msg("game_layer", "found no weapons hitting others tile");
|
||||
}
|
||||
else if(Index == TILE_NPH)
|
||||
{
|
||||
m_Tuning.Set("player_hooking", 0);
|
||||
dbg_msg("game_layer", "found no player hooking tile");
|
||||
}
|
||||
|
||||
if(Index >= ENTITY_OFFSET)
|
||||
{
|
||||
vec2 Pos(x * 32.0f + 16.0f, y * 32.0f + 16.0f);
|
||||
m_pController->OnEntity(Index - ENTITY_OFFSET, Pos, LAYER_GAME, pTiles[y * pTileMap->m_Width + x].m_Flags);
|
||||
}
|
||||
|
||||
if(pFront)
|
||||
{
|
||||
Index = pFront[y * pTileMap->m_Width + x].m_Index;
|
||||
if(Index == TILE_OLDLASER)
|
||||
{
|
||||
g_Config.m_SvOldLaser = 1;
|
||||
dbg_msg("front_layer", "found old laser tile");
|
||||
}
|
||||
else if(Index == TILE_NPC)
|
||||
{
|
||||
m_Tuning.Set("player_collision", 0);
|
||||
dbg_msg("front_layer", "found no collision tile");
|
||||
}
|
||||
else if(Index == TILE_EHOOK)
|
||||
{
|
||||
g_Config.m_SvEndlessDrag = 1;
|
||||
dbg_msg("front_layer", "found unlimited hook time tile");
|
||||
}
|
||||
else if(Index == TILE_NOHIT)
|
||||
{
|
||||
g_Config.m_SvHit = 0;
|
||||
dbg_msg("front_layer", "found no weapons hitting others tile");
|
||||
}
|
||||
else if(Index == TILE_NPH)
|
||||
{
|
||||
m_Tuning.Set("player_hooking", 0);
|
||||
dbg_msg("front_layer", "found no player hooking tile");
|
||||
}
|
||||
if(Index >= ENTITY_OFFSET)
|
||||
{
|
||||
vec2 Pos(x * 32.0f + 16.0f, y * 32.0f + 16.0f);
|
||||
m_pController->OnEntity(Index - ENTITY_OFFSET, Pos, LAYER_FRONT, pFront[y * pTileMap->m_Width + x].m_Flags);
|
||||
}
|
||||
}
|
||||
if(pSwitch)
|
||||
{
|
||||
Index = pSwitch[y * pTileMap->m_Width + x].m_Type;
|
||||
// TODO: Add off by default door here
|
||||
// if (Index == TILE_DOOR_OFF)
|
||||
if(Index >= ENTITY_OFFSET)
|
||||
{
|
||||
vec2 Pos(x * 32.0f + 16.0f, y * 32.0f + 16.0f);
|
||||
m_pController->OnEntity(Index - ENTITY_OFFSET, Pos, LAYER_SWITCH, pSwitch[y * pTileMap->m_Width + x].m_Flags, pSwitch[y * pTileMap->m_Width + x].m_Number);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//game.world.insert_entity(game.Controller);
|
||||
CreateAllEntities(true);
|
||||
|
||||
if(GIT_SHORTREV_HASH)
|
||||
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "git-revision", GIT_SHORTREV_HASH);
|
||||
|
@ -3557,6 +3448,107 @@ void CGameContext::OnInit(/*class IKernel *pKernel*/)
|
|||
#endif
|
||||
}
|
||||
|
||||
void CGameContext::CreateAllEntities(bool Initial)
|
||||
{
|
||||
const CMapItemLayerTilemap *pTileMap = m_Layers.GameLayer();
|
||||
const CTile *pTiles = static_cast<CTile *>(Kernel()->RequestInterface<IMap>()->GetData(pTileMap->m_Data));
|
||||
|
||||
const CTile *pFront = nullptr;
|
||||
if(m_Layers.FrontLayer())
|
||||
pFront = static_cast<CTile *>(Kernel()->RequestInterface<IMap>()->GetData(m_Layers.FrontLayer()->m_Front));
|
||||
|
||||
const CSwitchTile *pSwitch = nullptr;
|
||||
if(m_Layers.SwitchLayer())
|
||||
pSwitch = static_cast<CSwitchTile *>(Kernel()->RequestInterface<IMap>()->GetData(m_Layers.SwitchLayer()->m_Switch));
|
||||
|
||||
for(int y = 0; y < pTileMap->m_Height; y++)
|
||||
{
|
||||
for(int x = 0; x < pTileMap->m_Width; x++)
|
||||
{
|
||||
const int Index = y * pTileMap->m_Width + x;
|
||||
|
||||
// Game layer
|
||||
{
|
||||
const int GameIndex = pTiles[Index].m_Index;
|
||||
if(GameIndex == TILE_OLDLASER)
|
||||
{
|
||||
g_Config.m_SvOldLaser = 1;
|
||||
dbg_msg("game_layer", "found old laser tile");
|
||||
}
|
||||
else if(GameIndex == TILE_NPC)
|
||||
{
|
||||
m_Tuning.Set("player_collision", 0);
|
||||
dbg_msg("game_layer", "found no collision tile");
|
||||
}
|
||||
else if(GameIndex == TILE_EHOOK)
|
||||
{
|
||||
g_Config.m_SvEndlessDrag = 1;
|
||||
dbg_msg("game_layer", "found unlimited hook time tile");
|
||||
}
|
||||
else if(GameIndex == TILE_NOHIT)
|
||||
{
|
||||
g_Config.m_SvHit = 0;
|
||||
dbg_msg("game_layer", "found no weapons hitting others tile");
|
||||
}
|
||||
else if(GameIndex == TILE_NPH)
|
||||
{
|
||||
m_Tuning.Set("player_hooking", 0);
|
||||
dbg_msg("game_layer", "found no player hooking tile");
|
||||
}
|
||||
else if(GameIndex >= ENTITY_OFFSET)
|
||||
{
|
||||
m_pController->OnEntity(GameIndex - ENTITY_OFFSET, x, y, LAYER_GAME, pTiles[Index].m_Flags, Initial);
|
||||
}
|
||||
}
|
||||
|
||||
if(pFront)
|
||||
{
|
||||
const int FrontIndex = pFront[Index].m_Index;
|
||||
if(FrontIndex == TILE_OLDLASER)
|
||||
{
|
||||
g_Config.m_SvOldLaser = 1;
|
||||
dbg_msg("front_layer", "found old laser tile");
|
||||
}
|
||||
else if(FrontIndex == TILE_NPC)
|
||||
{
|
||||
m_Tuning.Set("player_collision", 0);
|
||||
dbg_msg("front_layer", "found no collision tile");
|
||||
}
|
||||
else if(FrontIndex == TILE_EHOOK)
|
||||
{
|
||||
g_Config.m_SvEndlessDrag = 1;
|
||||
dbg_msg("front_layer", "found unlimited hook time tile");
|
||||
}
|
||||
else if(FrontIndex == TILE_NOHIT)
|
||||
{
|
||||
g_Config.m_SvHit = 0;
|
||||
dbg_msg("front_layer", "found no weapons hitting others tile");
|
||||
}
|
||||
else if(FrontIndex == TILE_NPH)
|
||||
{
|
||||
m_Tuning.Set("player_hooking", 0);
|
||||
dbg_msg("front_layer", "found no player hooking tile");
|
||||
}
|
||||
else if(FrontIndex >= ENTITY_OFFSET)
|
||||
{
|
||||
m_pController->OnEntity(FrontIndex - ENTITY_OFFSET, x, y, LAYER_FRONT, pFront[Index].m_Flags, Initial);
|
||||
}
|
||||
}
|
||||
|
||||
if(pSwitch)
|
||||
{
|
||||
const int SwitchType = pSwitch[Index].m_Type;
|
||||
// TODO: Add off by default door here
|
||||
// if(SwitchType == TILE_DOOR_OFF)
|
||||
if(SwitchType >= ENTITY_OFFSET)
|
||||
{
|
||||
m_pController->OnEntity(SwitchType - ENTITY_OFFSET, x, y, LAYER_SWITCH, pSwitch[Index].m_Flags, Initial, pSwitch[Index].m_Number);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CGameContext::DeleteTempfile()
|
||||
{
|
||||
if(m_aDeleteTempfile[0] != 0)
|
||||
|
@ -3864,16 +3856,16 @@ void CGameContext::SendRecord(int ClientID)
|
|||
}
|
||||
}
|
||||
|
||||
int CGameContext::ProcessSpamProtection(int ClientID, bool RespectChatInitialDelay)
|
||||
bool CGameContext::ProcessSpamProtection(int ClientID, bool RespectChatInitialDelay)
|
||||
{
|
||||
if(!m_apPlayers[ClientID])
|
||||
return 0;
|
||||
return false;
|
||||
if(g_Config.m_SvSpamprotection && m_apPlayers[ClientID]->m_LastChat && m_apPlayers[ClientID]->m_LastChat + Server()->TickSpeed() * g_Config.m_SvChatDelay > Server()->Tick())
|
||||
return 1;
|
||||
return true;
|
||||
else if(g_Config.m_SvDnsblChat && Server()->DnsblBlack(ClientID))
|
||||
{
|
||||
SendChatTarget(ClientID, "Players are not allowed to chat from VPNs at this time");
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
m_apPlayers[ClientID]->m_LastChat = Server()->Tick();
|
||||
|
@ -3896,17 +3888,17 @@ int CGameContext::ProcessSpamProtection(int ClientID, bool RespectChatInitialDel
|
|||
char aBuf[128];
|
||||
str_format(aBuf, sizeof aBuf, "You are not permitted to talk for the next %d seconds.", Muted);
|
||||
SendChatTarget(ClientID, aBuf);
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
if(g_Config.m_SvSpamMuteDuration && (m_apPlayers[ClientID]->m_ChatScore += g_Config.m_SvChatPenalty) > g_Config.m_SvChatThreshold)
|
||||
{
|
||||
Mute(&Addr, g_Config.m_SvSpamMuteDuration, Server()->ClientName(ClientID));
|
||||
m_apPlayers[ClientID]->m_ChatScore = 0;
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
int CGameContext::GetDDRaceTeam(int ClientID)
|
||||
|
@ -3934,16 +3926,14 @@ bool CheckClientID2(int ClientID)
|
|||
|
||||
void CGameContext::Whisper(int ClientID, char *pStr)
|
||||
{
|
||||
char *pName;
|
||||
char *pMessage;
|
||||
int Error = 0;
|
||||
|
||||
if(ProcessSpamProtection(ClientID))
|
||||
return;
|
||||
|
||||
pStr = str_skip_whitespaces(pStr);
|
||||
|
||||
char *pName;
|
||||
int Victim;
|
||||
bool Error = false;
|
||||
|
||||
// add token
|
||||
if(*pStr == '"')
|
||||
|
@ -3967,7 +3957,7 @@ void CGameContext::Whisper(int ClientID, char *pStr)
|
|||
}
|
||||
else if(pStr[0] == 0)
|
||||
{
|
||||
Error = 1;
|
||||
Error = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -3995,7 +3985,7 @@ void CGameContext::Whisper(int ClientID, char *pStr)
|
|||
{
|
||||
if(pStr[0] == 0)
|
||||
{
|
||||
Error = 1;
|
||||
Error = true;
|
||||
break;
|
||||
}
|
||||
if(pStr[0] == ' ')
|
||||
|
@ -4016,14 +4006,13 @@ void CGameContext::Whisper(int ClientID, char *pStr)
|
|||
|
||||
if(pStr[0] != ' ')
|
||||
{
|
||||
Error = 1;
|
||||
Error = true;
|
||||
}
|
||||
|
||||
*pStr = 0;
|
||||
pStr++;
|
||||
|
||||
pMessage = pStr;
|
||||
|
||||
char *pMessage = pStr;
|
||||
char aBuf[256];
|
||||
|
||||
if(Error)
|
||||
|
|
|
@ -187,6 +187,8 @@ public:
|
|||
char m_aaZoneEnterMsg[NUM_TUNEZONES][256]; // 0 is used for switching from or to area without tunings
|
||||
char m_aaZoneLeaveMsg[NUM_TUNEZONES][256];
|
||||
|
||||
void CreateAllEntities(bool Initial);
|
||||
|
||||
char m_aDeleteTempfile[128];
|
||||
void DeleteTempfile();
|
||||
|
||||
|
@ -287,7 +289,7 @@ public:
|
|||
void OnPreTickTeehistorian() override;
|
||||
bool OnClientDDNetVersionKnown(int ClientID);
|
||||
void FillAntibot(CAntibotRoundData *pData) override;
|
||||
int ProcessSpamProtection(int ClientID, bool RespectChatInitialDelay = true);
|
||||
bool ProcessSpamProtection(int ClientID, bool RespectChatInitialDelay = true);
|
||||
int GetDDRaceTeam(int ClientID);
|
||||
// Describes the time when the first player joined the server.
|
||||
int64_t m_NonEmptySince;
|
||||
|
|
|
@ -37,10 +37,6 @@ IGameController::IGameController(class CGameContext *pGameServer)
|
|||
m_UnbalancedTick = -1;
|
||||
m_ForceBalanced = false;
|
||||
|
||||
m_aNumSpawnPoints[0] = 0;
|
||||
m_aNumSpawnPoints[1] = 0;
|
||||
m_aNumSpawnPoints[2] = 0;
|
||||
|
||||
m_CurrentRecord = 0;
|
||||
}
|
||||
|
||||
|
@ -119,15 +115,14 @@ void IGameController::EvaluateSpawnType(CSpawnEval *pEval, int Type, int DDTeam)
|
|||
for(int j = 0; j < 2 && !pEval->m_Got; j++)
|
||||
{
|
||||
// get spawn point
|
||||
for(int i = 0; i < m_aNumSpawnPoints[Type]; i++)
|
||||
for(const vec2 &SpawnPoint : m_avSpawnPoints[Type])
|
||||
{
|
||||
vec2 P = m_aaSpawnPoints[Type][i];
|
||||
|
||||
vec2 P = SpawnPoint;
|
||||
if(j == 0)
|
||||
{
|
||||
// check if the position is occupado
|
||||
CEntity *apEnts[MAX_CLIENTS];
|
||||
int Num = GameServer()->m_World.FindEntities(m_aaSpawnPoints[Type][i], 64, apEnts, MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER);
|
||||
int Num = GameServer()->m_World.FindEntities(SpawnPoint, 64, apEnts, MAX_CLIENTS, CGameWorld::ENTTYPE_CHARACTER);
|
||||
vec2 aPositions[5] = {vec2(0.0f, 0.0f), vec2(-32.0f, 0.0f), vec2(0.0f, -32.0f), vec2(32.0f, 0.0f), vec2(0.0f, 32.0f)}; // start, left, up, right, down
|
||||
int Result = -1;
|
||||
for(int Index = 0; Index < 5 && Result == -1; ++Index)
|
||||
|
@ -138,8 +133,8 @@ void IGameController::EvaluateSpawnType(CSpawnEval *pEval, int Type, int DDTeam)
|
|||
for(int c = 0; c < Num; ++c)
|
||||
{
|
||||
CCharacter *pChr = static_cast<CCharacter *>(apEnts[c]);
|
||||
if(GameServer()->Collision()->CheckPoint(m_aaSpawnPoints[Type][i] + aPositions[Index]) ||
|
||||
distance(pChr->m_Pos, m_aaSpawnPoints[Type][i] + aPositions[Index]) <= pChr->GetProximityRadius())
|
||||
if(GameServer()->Collision()->CheckPoint(SpawnPoint + aPositions[Index]) ||
|
||||
distance(pChr->m_Pos, SpawnPoint + aPositions[Index]) <= pChr->GetProximityRadius())
|
||||
{
|
||||
Result = -1;
|
||||
break;
|
||||
|
@ -165,12 +160,11 @@ void IGameController::EvaluateSpawnType(CSpawnEval *pEval, int Type, int DDTeam)
|
|||
|
||||
bool IGameController::CanSpawn(int Team, vec2 *pOutPos, int DDTeam)
|
||||
{
|
||||
CSpawnEval Eval;
|
||||
|
||||
// spectators can't spawn
|
||||
if(Team == TEAM_SPECTATORS)
|
||||
return false;
|
||||
|
||||
CSpawnEval Eval;
|
||||
EvaluateSpawnType(&Eval, 0, DDTeam);
|
||||
EvaluateSpawnType(&Eval, 1, DDTeam);
|
||||
EvaluateSpawnType(&Eval, 2, DDTeam);
|
||||
|
@ -179,14 +173,12 @@ bool IGameController::CanSpawn(int Team, vec2 *pOutPos, int DDTeam)
|
|||
return Eval.m_Got;
|
||||
}
|
||||
|
||||
bool IGameController::OnEntity(int Index, vec2 Pos, int Layer, int Flags, int Number)
|
||||
bool IGameController::OnEntity(int Index, int x, int y, int Layer, int Flags, bool Initial, int Number)
|
||||
{
|
||||
if(Index < 0)
|
||||
return false;
|
||||
dbg_assert(Index >= 0, "Invalid entity index");
|
||||
|
||||
const vec2 Pos(x * 32.0f + 16.0f, y * 32.0f + 16.0f);
|
||||
|
||||
int x, y;
|
||||
x = (Pos.x - 16.0f) / 32.0f;
|
||||
y = (Pos.y - 16.0f) / 32.0f;
|
||||
int aSides[8];
|
||||
aSides[0] = GameServer()->Collision()->Entity(x, y + 1, Layer);
|
||||
aSides[1] = GameServer()->Collision()->Entity(x + 1, y + 1, Layer);
|
||||
|
@ -197,13 +189,11 @@ bool IGameController::OnEntity(int Index, vec2 Pos, int Layer, int Flags, int Nu
|
|||
aSides[6] = GameServer()->Collision()->Entity(x - 1, y, Layer);
|
||||
aSides[7] = GameServer()->Collision()->Entity(x - 1, y + 1, Layer);
|
||||
|
||||
if(Index >= ENTITY_SPAWN && Index <= ENTITY_SPAWN_BLUE)
|
||||
if(Index >= ENTITY_SPAWN && Index <= ENTITY_SPAWN_BLUE && Initial)
|
||||
{
|
||||
int Type = Index - ENTITY_SPAWN;
|
||||
m_aaSpawnPoints[Type][m_aNumSpawnPoints[Type]] = Pos;
|
||||
m_aNumSpawnPoints[Type] = minimum(m_aNumSpawnPoints[Type] + 1, (int)std::size(m_aaSpawnPoints[0]));
|
||||
const int Type = Index - ENTITY_SPAWN;
|
||||
m_avSpawnPoints[Type].push_back(Pos);
|
||||
}
|
||||
|
||||
else if(Index == ENTITY_DOOR)
|
||||
{
|
||||
for(int i = 0; i < 8; i++)
|
||||
|
@ -322,7 +312,6 @@ bool IGameController::OnEntity(int Index, vec2 Pos, int Layer, int Flags, int Nu
|
|||
aSides2[6] = GameServer()->Collision()->Entity(x - 2, y, Layer);
|
||||
aSides2[7] = GameServer()->Collision()->Entity(x - 2, y + 2, Layer);
|
||||
|
||||
float AngularSpeed = 0.0f;
|
||||
int Ind = Index - ENTITY_LASER_STOP;
|
||||
int M;
|
||||
if(Ind < 0)
|
||||
|
@ -335,6 +324,7 @@ bool IGameController::OnEntity(int Index, vec2 Pos, int Layer, int Flags, int Nu
|
|||
else
|
||||
M = -1;
|
||||
|
||||
float AngularSpeed = 0.0f;
|
||||
if(Ind == 0)
|
||||
AngularSpeed = 0.0f;
|
||||
else if(Ind == 1)
|
||||
|
@ -454,8 +444,6 @@ const char *IGameController::GetTeamName(int Team)
|
|||
return "spectators";
|
||||
}
|
||||
|
||||
//static bool IsSeparator(char c) { return c == ';' || c == ' ' || c == ',' || c == '\t'; }
|
||||
|
||||
void IGameController::StartRound()
|
||||
{
|
||||
ResetGame();
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#include <base/vmath.h>
|
||||
#include <engine/map.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
/*
|
||||
Class: Game Controller
|
||||
Controls the main game logic. Keeping track of team and player score,
|
||||
|
@ -15,8 +17,7 @@ class IGameController
|
|||
{
|
||||
friend class CSaveTeam; // need access to GameServer() and Server()
|
||||
|
||||
vec2 m_aaSpawnPoints[3][64];
|
||||
int m_aNumSpawnPoints[3];
|
||||
std::vector<vec2> m_avSpawnPoints[3];
|
||||
|
||||
class CGameContext *m_pGameServer;
|
||||
class CConfig *m_pConfig;
|
||||
|
@ -103,7 +104,7 @@ public:
|
|||
Returns:
|
||||
bool?
|
||||
*/
|
||||
virtual bool OnEntity(int Index, vec2 Pos, int Layer, int Flags, int Number = 0);
|
||||
virtual bool OnEntity(int Index, int x, int y, int Layer, int Flags, bool Initial, int Number = 0);
|
||||
|
||||
virtual void OnPlayerConnect(class CPlayer *pPlayer);
|
||||
virtual void OnPlayerDisconnect(class CPlayer *pPlayer, const char *pReason);
|
||||
|
|
|
@ -146,6 +146,8 @@ void CGameWorld::Reset()
|
|||
RemoveEntities();
|
||||
|
||||
m_ResetRequested = false;
|
||||
|
||||
GameServer()->CreateAllEntities(false);
|
||||
}
|
||||
|
||||
void CGameWorld::RemoveEntities()
|
||||
|
|
Loading…
Reference in a new issue