18 changes: 13 additions & 5 deletions src/game/editor/layer_tiles.cpp
Expand Up @@ -508,10 +508,10 @@ void CLayerTiles::BrushFlipX()
m_pTiles[y*m_Width+m_Width-1-x] = Tmp;
}

if(m_Tele || m_Switch || m_Speedup || m_Tune)
if(m_Tele || m_Speedup || m_Tune)
return;

bool Rotate = !(m_Game || m_Front) || m_pEditor->m_AllowPlaceUnusedTiles;
bool Rotate = !(m_Game || m_Front || m_Switch) || m_pEditor->m_AllowPlaceUnusedTiles;
for(int y = 0; y < m_Height; y++)
for(int x = 0; x < m_Width; x++)
if(!Rotate && !IsRotatableTile(m_pTiles[y*m_Width+x].m_Index))
Expand All @@ -530,10 +530,10 @@ void CLayerTiles::BrushFlipY()
m_pTiles[(m_Height-1-y)*m_Width+x] = Tmp;
}

if(m_Tele || m_Switch || m_Speedup || m_Tune)
if(m_Tele || m_Speedup || m_Tune)
return;

bool Rotate = !(m_Game || m_Front) || m_pEditor->m_AllowPlaceUnusedTiles;
bool Rotate = !(m_Game || m_Front || m_Switch) || m_pEditor->m_AllowPlaceUnusedTiles;
for(int y = 0; y < m_Height; y++)
for(int x = 0; x < m_Width; x++)
if(!Rotate && !IsRotatableTile(m_pTiles[y*m_Width+x].m_Index))
Expand Down Expand Up @@ -861,7 +861,7 @@ int CLayerTiles::RenderProperties(CUIRect *pToolBox)
{"Shift by", m_pEditor->m_ShiftBy, PROPTYPE_INT_SCROLL, 1, 100000},
{"Image", m_Image, PROPTYPE_IMAGE, 0, 0},
{"Color", Color, PROPTYPE_COLOR, 0, 0},
{"Color Env", m_ColorEnv+1, PROPTYPE_INT_STEP, 0, m_pEditor->m_Map.m_lEnvelopes.size()+1},
{"Color Env", m_ColorEnv+1, PROPTYPE_ENVELOPE, 0, 0},
{"Color TO", m_ColorEnvOffset, PROPTYPE_INT_SCROLL, -1000000, 1000000},
{"Auto Rule", m_AutoMapperConfig, PROPTYPE_AUTOMAPPER, m_Image, 0},
{"Seed", m_Seed, PROPTYPE_INT_SCROLL, 0, 1000000000},
Expand Down Expand Up @@ -976,6 +976,7 @@ void CLayerTiles::ModifyImageIndex(INDEX_MODIFY_FUNC Func)

void CLayerTiles::ModifyEnvelopeIndex(INDEX_MODIFY_FUNC Func)
{
Func(&m_ColorEnv);
}

CLayerTele::CLayerTele(int w, int h)
Expand Down Expand Up @@ -1731,6 +1732,7 @@ void CLayerSwitch::BrushDraw(CLayer *pBrush, float wx, float wy)
m_pSwitchTile[fy*m_Width+fx].m_Type = l->m_pTiles[y*l->m_Width+x].m_Index;
m_pSwitchTile[fy*m_Width+fx].m_Flags = l->m_pTiles[y*l->m_Width+x].m_Flags;
m_pTiles[fy*m_Width+fx].m_Index = l->m_pTiles[y*l->m_Width+x].m_Index;
m_pTiles[fy*m_Width+fx].m_Flags = l->m_pTiles[y*l->m_Width+x].m_Flags;
}
else
{
Expand Down Expand Up @@ -1800,6 +1802,12 @@ void CLayerSwitch::BrushRotate(float Amount)
{
*pDst1 = pTempData1[y*m_Width+x];
*pDst2 = pTempData2[y*m_Width+x];
if(IsRotatableTile(pDst2->m_Index))
{
if(pDst2->m_Flags&TILEFLAG_ROTATE)
pDst2->m_Flags ^= (TILEFLAG_HFLIP|TILEFLAG_VFLIP);
pDst2->m_Flags ^= TILEFLAG_ROTATE;
}
}

int Temp = m_Width;
Expand Down
8 changes: 4 additions & 4 deletions src/game/editor/popups.cpp
Expand Up @@ -570,9 +570,9 @@ int CEditor::PopupQuad(CEditor *pEditor, CUIRect View)
CProperty aProps[] = {
{"Pos X", pCurrentQuad->m_aPoints[4].x/1000, PROPTYPE_INT_SCROLL, -1000000, 1000000},
{"Pos Y", pCurrentQuad->m_aPoints[4].y/1000, PROPTYPE_INT_SCROLL, -1000000, 1000000},
{"Pos. Env", pCurrentQuad->m_PosEnv+1, PROPTYPE_INT_STEP, 0, pEditor->m_Map.m_lEnvelopes.size()+1},
{"Pos. Env", pCurrentQuad->m_PosEnv+1, PROPTYPE_ENVELOPE, 0, 0},
{"Pos. TO", pCurrentQuad->m_PosEnvOffset, PROPTYPE_INT_SCROLL, -1000000, 1000000},
{"Color Env", pCurrentQuad->m_ColorEnv+1, PROPTYPE_INT_STEP, 0, pEditor->m_Map.m_lEnvelopes.size()+1},
{"Color Env", pCurrentQuad->m_ColorEnv+1, PROPTYPE_ENVELOPE, 0, 0},
{"Color TO", pCurrentQuad->m_ColorEnvOffset, PROPTYPE_INT_SCROLL, -1000000, 1000000},

{0},
Expand Down Expand Up @@ -712,9 +712,9 @@ int CEditor::PopupSource(CEditor *pEditor, CUIRect View)
{"Pan", pSource->m_Pan, PROPTYPE_BOOL, 0, 1},
{"Delay", pSource->m_TimeDelay, PROPTYPE_INT_SCROLL, 0, 1000000},
{"Falloff", pSource->m_Falloff, PROPTYPE_INT_SCROLL, 0, 255},
{"Pos. Env", pSource->m_PosEnv+1, PROPTYPE_INT_STEP, 0, pEditor->m_Map.m_lEnvelopes.size()+1},
{"Pos. Env", pSource->m_PosEnv+1, PROPTYPE_ENVELOPE, 0, 0},
{"Pos. TO", pSource->m_PosEnvOffset, PROPTYPE_INT_SCROLL, -1000000, 1000000},
{"Sound Env", pSource->m_SoundEnv+1, PROPTYPE_INT_STEP, 0, pEditor->m_Map.m_lEnvelopes.size()+1},
{"Sound Env", pSource->m_SoundEnv+1, PROPTYPE_ENVELOPE, 0, 0},
{"Sound. TO", pSource->m_PosEnvOffset, PROPTYPE_INT_SCROLL, -1000000, 1000000},

{0},
Expand Down
10 changes: 1 addition & 9 deletions src/game/gamecore.cpp
Expand Up @@ -494,15 +494,7 @@ void CCharacterCore::Move()
if((!(pCharCore->m_Super || m_Super) && (m_Solo || pCharCore->m_Solo || !pCharCore->m_Collision || pCharCore->m_NoCollision || (m_Id != -1 && !m_pTeams->CanCollide(m_Id, p)))))
continue;
float D = distance(Pos, pCharCore->m_Pos);
if(D < 28.0f && D > 0.0f)
{
if(a > 0.0f)
m_Pos = LastPos;
else if(distance(NewPos, pCharCore->m_Pos) > D)
m_Pos = NewPos;
return;
}
else if(D <= 0.001f && D >= -0.001f)
if(D < 28.0f && D >= 0.0f)
{
if(a > 0.0f)
m_Pos = LastPos;
Expand Down
17 changes: 15 additions & 2 deletions src/game/server/ddracechat.cpp
Expand Up @@ -63,6 +63,19 @@ void CGameContext::ConInfo(IConsole::IResult *pResult, void *pUserData)
"Or visit DDNet.tw");
}

void CGameContext::ConList(IConsole::IResult *pResult, void *pUserData)
{
CGameContext *pSelf = (CGameContext *)pUserData;
int ClientID = pResult->m_ClientID;
if(!CheckClientID(ClientID)) return;

char zerochar = 0;
if(pResult->NumArguments() > 0)
pSelf->List(ClientID, pResult->GetString(0));
else
pSelf->List(ClientID, &zerochar);
}

void CGameContext::ConHelp(IConsole::IResult *pResult, void *pUserData)
{
CGameContext *pSelf = (CGameContext *) pUserData;
Expand Down Expand Up @@ -607,12 +620,12 @@ void CGameContext::ConSave(IConsole::IResult *pResult, void *pUserData)
if(pCode[3] == ' ')
{
str_copy(aCountry, pCode, 4);
pCode = pCode + 4;
pCode = str_skip_whitespaces_const(pCode + 4);
}
else if(str_length(pCode) > 4 && pCode[4] == ' ')
{
str_copy(aCountry, pCode, 5);
pCode = pCode + 5;
pCode = str_skip_whitespaces_const(pCode + 5);
}
else
{
Expand Down
1 change: 1 addition & 0 deletions src/game/server/ddracechat.h
Expand Up @@ -13,6 +13,7 @@ CHAT_COMMAND("eyeemote", "?s['on'|'off'|'toggle']", CFGFLAG_CHAT|CFGFLAG_SERVER,
CHAT_COMMAND("settings", "?s[configname]", CFGFLAG_CHAT|CFGFLAG_SERVER, ConSettings, this, "Shows gameplay information for this server")
CHAT_COMMAND("help", "?r[command]", CFGFLAG_CHAT|CFGFLAG_SERVER, ConHelp, this, "Shows help to command r, general help if left blank")
CHAT_COMMAND("info", "", CFGFLAG_CHAT|CFGFLAG_SERVER, ConInfo, this, "Shows info about this server")
CHAT_COMMAND("list", "?s[filter]", CFGFLAG_CHAT, ConList, this, "List connected players with optional case-insensitive substring matching filter")
CHAT_COMMAND("me", "r[message]", CFGFLAG_CHAT|CFGFLAG_SERVER|CFGFLAG_NONTEEHISTORIC, ConMe, this, "Like the famous irc command '/me says hi' will display '<yourname> says hi'")
CHAT_COMMAND("w", "s[player name] r[message]", CFGFLAG_CHAT|CFGFLAG_SERVER|CFGFLAG_NONTEEHISTORIC, ConWhisper, this, "Whisper something to someone (private message)")
CHAT_COMMAND("whisper", "s[player name] r[message]", CFGFLAG_CHAT|CFGFLAG_SERVER|CFGFLAG_NONTEEHISTORIC, ConWhisper, this, "Whisper something to someone (private message)")
Expand Down
40 changes: 26 additions & 14 deletions src/game/server/ddracecommands.cpp
Expand Up @@ -3,6 +3,7 @@
#include <engine/shared/config.h>
#include <game/server/teams.h>
#include <game/server/gamemodes/DDRace.h>
#include <game/server/save.h>
#include <game/version.h>
#if defined(CONF_SQL)
#include <game/server/score/sql_score.h>
Expand Down Expand Up @@ -639,20 +640,6 @@ void CGameContext::ConModerate(IConsole::IResult *pResult, void *pUserData)
pSelf->SendChatTarget(pResult->m_ClientID, "Active moderator mode disabled for you.");
}

void CGameContext::ConList(IConsole::IResult *pResult, void *pUserData)
{
CGameContext *pSelf = (CGameContext *)pUserData;
int ClientID = pResult->m_ClientID;
if(!CheckClientID(ClientID)) return;

char zerochar = 0;
if(pResult->NumArguments() > 0)
pSelf->List(ClientID, pResult->GetString(0));
else
pSelf->List(ClientID, &zerochar);
}


void CGameContext::ConSetDDRTeam(IConsole::IResult *pResult, void *pUserData)
{
CGameContext *pSelf = (CGameContext *)pUserData;
Expand Down Expand Up @@ -719,3 +706,28 @@ void CGameContext::ConVoteNo(IConsole::IResult *pResult, void *pUserData)

pSelf->ForceVote(pResult->m_ClientID, false);
}

void CGameContext::ConDrySave(IConsole::IResult *pResult, void *pUserData)
{
CGameContext *pSelf = (CGameContext *)pUserData;

CPlayer *pPlayer = pSelf->m_apPlayers[pResult->m_ClientID];

if(!pPlayer || pSelf->Server()->GetAuthedState(pResult->m_ClientID) != AUTHED_ADMIN)
return;

CSaveTeam SavedTeam(pSelf->m_pController);
int Result = SavedTeam.save(pPlayer->GetTeam());
if(CSaveTeam::HandleSaveError(Result, pResult->m_ClientID, pSelf))
return;

char aBuf[64];
str_format(aBuf, sizeof(aBuf), "%s-%lld-%s.save", pSelf->Server()->GetMapName(), time_get(), pSelf->Server()->GetAuthName(pResult->m_ClientID));
IOHANDLE File = pSelf->Storage()->OpenFile(aBuf, IOFLAG_WRITE, IStorage::TYPE_ALL);
if(!File)
return;

int Len = str_length(SavedTeam.GetString());
io_write(File, SavedTeam.GetString(), Len);
io_close(File);
}
3 changes: 3 additions & 0 deletions src/game/server/entities/character.cpp
Expand Up @@ -1152,6 +1152,9 @@ void CCharacter::Snap(int SnappingClient)
pCharacter->m_PlayerFlags = GetPlayer()->m_PlayerFlags;

CNetObj_DDNetCharacter *pDDNetCharacter = static_cast<CNetObj_DDNetCharacter *>(Server()->SnapNewItem(NETOBJTYPE_DDNETCHARACTER, id, sizeof(CNetObj_DDNetCharacter)));
if(!pDDNetCharacter)
return;

pDDNetCharacter->m_Flags = 0;
if(m_Solo)
pDDNetCharacter->m_Flags |= CHARACTERFLAG_SOLO;
Expand Down
2 changes: 1 addition & 1 deletion src/game/server/gamecontext.cpp
Expand Up @@ -2874,7 +2874,7 @@ void CGameContext::OnMapChange(char *pNewMapName, int MapNameSize)
char aConfig[128];
char aTemp[128];
str_format(aConfig, sizeof(aConfig), "maps/%s.cfg", g_Config.m_SvMap);
str_format(aTemp, sizeof(aTemp), "%s.temp.%d", pNewMapName, pid());
str_format(aTemp, sizeof(aTemp), "%s.%d.tmp", pNewMapName, pid());

IOHANDLE File = Storage()->OpenFile(aConfig, IOFLAG_READ, IStorage::TYPE_ALL);
if(!File)
Expand Down
1 change: 1 addition & 0 deletions src/game/server/gamecontext.h
Expand Up @@ -111,6 +111,7 @@ class CGameContext : public IGameServer
static void ConClearVotes(IConsole::IResult *pResult, void *pUserData);
static void ConVote(IConsole::IResult *pResult, void *pUserData);
static void ConVoteNo(IConsole::IResult *pResult, void *pUserData);
static void ConDrySave(IConsole::IResult *pResult, void *pUserData);
static void ConchainSpecialMotdupdate(IConsole::IResult *pResult, void *pUserData, IConsole::FCommandCallback pfnCallback, void *pCallbackUserData);

CGameContext(int Resetting);
Expand Down
23 changes: 23 additions & 0 deletions src/game/server/save.cpp
Expand Up @@ -279,6 +279,29 @@ int CSaveTeam::save(int Team)
return 1;
}

bool CSaveTeam::HandleSaveError(int Result, int ClientID, CGameContext *pGameContext)
{
switch(Result)
{
case 1:
pGameContext->SendChatTarget(ClientID, "You have to be in a team (from 1-63)");
break;
case 2:
pGameContext->SendChatTarget(ClientID, "Could not find your Team");
break;
case 3:
pGameContext->SendChatTarget(ClientID, "Unable to find all Characters");
break;
case 4:
pGameContext->SendChatTarget(ClientID, "Your team is not started yet");
break;
default:
return false;
}

return true;
}

int CSaveTeam::load(int Team)
{
if(Team <= 0 || Team >= MAX_CLIENTS)
Expand Down
1 change: 1 addition & 0 deletions src/game/server/save.h
Expand Up @@ -100,6 +100,7 @@ class CSaveTeam
int load(int Team);
CSaveTee* SavedTees;

static bool HandleSaveError(int Result, int ClientID, CGameContext *pGameContext);
private:
int MatchPlayer(char name[16]);
CCharacter* MatchCharacter(char name[16], int SaveID);
Expand Down
1 change: 1 addition & 0 deletions src/game/server/score/file_score.h
Expand Up @@ -6,6 +6,7 @@

#include <base/tl/sorted_array.h>

#include <string>
#include "../score.h"

class CFileScore: public IScore
Expand Down
20 changes: 4 additions & 16 deletions src/game/server/score/sql_score.cpp
Expand Up @@ -626,7 +626,7 @@ bool CSqlScore::SaveTeamScoreThread(CSqlServer* pSqlServer, const CSqlData *pGam
char aUpdateID[17];
aUpdateID[0] = 0;

str_format(aBuf, sizeof(aBuf), "SELECT Name, l.ID, Time FROM ((SELECT ID FROM %s_teamrace WHERE Map = '%s' AND Name = '%s') as l) LEFT JOIN %s_teamrace as r ON l.ID = r.ID ORDER BY ID;", pSqlServer->GetPrefix(), pData->m_Map.ClrStr(), pData->m_aNames[0].ClrStr(), pSqlServer->GetPrefix());
str_format(aBuf, sizeof(aBuf), "SELECT Name, l.ID, Time FROM ((SELECT ID FROM %s_teamrace WHERE Map = '%s' AND Name = '%s' and DDNet7 = false) as l) LEFT JOIN %s_teamrace as r ON l.ID = r.ID ORDER BY ID;", pSqlServer->GetPrefix(), pData->m_Map.ClrStr(), pData->m_aNames[0].ClrStr(), pSqlServer->GetPrefix());
pSqlServer->executeSqlQuery(aBuf);

if (pSqlServer->GetResults()->rowsCount() > 0)
Expand Down Expand Up @@ -1409,21 +1409,9 @@ bool CSqlScore::SaveTeamThread(CSqlServer* pSqlServer, const CSqlData *pGameData
{
CSaveTeam SavedTeam(pData->GameServer()->m_pController);
Num = SavedTeam.save(Team);
switch (Num)
{
case 1:
pData->GameServer()->SendChatTarget(pData->m_ClientID, "You have to be in a team (from 1-63)");
break;
case 2:
pData->GameServer()->SendChatTarget(pData->m_ClientID, "Could not find your Team");
break;
case 3:
pData->GameServer()->SendChatTarget(pData->m_ClientID, "Unable to find all Characters");
break;
case 4:
pData->GameServer()->SendChatTarget(pData->m_ClientID, "Your team is not started yet");
break;
}
if(CSaveTeam::HandleSaveError(Num, pData->m_ClientID, pData->GameServer()))
return true;

if(!Num)
{
str_copy(TeamString, SavedTeam.GetString(), sizeof(TeamString));
Expand Down
10 changes: 10 additions & 0 deletions src/game/variables.h
Expand Up @@ -164,6 +164,16 @@ MACRO_CONFIG_INT(SvSendVotesPerTick, sv_send_votes_per_tick, 5, 1, 15, CFGFLAG_S
MACRO_CONFIG_INT(SvRescue, sv_rescue, 0, 0, 1, CFGFLAG_SERVER, "Allow /rescue command so players can teleport themselves out of freeze")
MACRO_CONFIG_INT(SvRescueDelay, sv_rescue_delay, 5, 0, 1000, CFGFLAG_SERVER, "Number of seconds between two rescues")

#if defined(CONF_VIDEORECORDER)
MACRO_CONFIG_INT(ClVideoShowhud, cl_video_showhud, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Show ingame HUD when rendering video")
MACRO_CONFIG_INT(ClVideoShowChat, cl_video_showchat, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Show chat when rendering video")
MACRO_CONFIG_INT(ClVideoSndEnable, cl_video_sound_enable, 1, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Use sound when rendering video")
MACRO_CONFIG_INT(ClVideoShowHookCollOther, cl_video_showhookcollother, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Show other players' hook collision lines when rendering video")
MACRO_CONFIG_INT(ClVideoShowDirection, cl_video_showdirection, 0, 0, 1, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Show other players' key presses when rendering video")
MACRO_CONFIG_INT(ClVideoX264Crf, cl_video_crf, 22, 0, 51, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Set crf when encode video with libx264")
MACRO_CONFIG_INT(ClVideoX264Preset, cl_video_preset, 6, 0, 9, CFGFLAG_CLIENT|CFGFLAG_SAVE, "Set preset when encode video with libx264, default is 6(slow), 0 is ultrafast, 9 is placebo(the slowest, not recommend)")
#endif

// debug
#ifdef CONF_DEBUG // this one can crash the server if not used correctly
MACRO_CONFIG_INT(DbgDummies, dbg_dummies, 0, 0, 15, CFGFLAG_SERVER, "")
Expand Down
6 changes: 3 additions & 3 deletions src/game/version.h
Expand Up @@ -2,9 +2,9 @@
/* If you are missing that file, acquire a complete release at teeworlds.com. */
#ifndef GAME_VERSION_H
#define GAME_VERSION_H
#define GAME_VERSION "0.6.4, 12.8.1"
#define GAME_VERSION "0.6.4, 12.9.2"
#define GAME_NETVERSION "0.6 626fce9a778df4d4"
#define GAME_RELEASE_VERSION "12.8.1"
#define CLIENT_VERSIONNR 12081
#define GAME_RELEASE_VERSION "12.9.2"
#define CLIENT_VERSIONNR 12092
extern const char *GIT_SHORTREV_HASH;
#endif
4 changes: 2 additions & 2 deletions src/tools/map_convert_07.cpp
Expand Up @@ -135,7 +135,7 @@ int main(int argc, const char **argv)

png_init(0,0);

g_NextDataItemID = g_DataReader.NumItems();
g_NextDataItemID = g_DataReader.NumData();

// add all items
for(int Index = 0; Index < g_DataReader.NumItems(); Index++)
Expand All @@ -150,7 +150,7 @@ int main(int argc, const char **argv)
}

// add all data
for(int Index = 0; Index < g_DataReader.NumItems(); Index++)
for(int Index = 0; Index < g_DataReader.NumData(); Index++)
{
pData = g_DataReader.GetData(Index);
Size = g_DataReader.GetDataSize(Index);
Expand Down