Skip to content

Commit

Permalink
fix #6107 #6108
Browse files Browse the repository at this point in the history
  • Loading branch information
rt committed Dec 24, 2018
1 parent de62abb commit 0b10bc8
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 68 deletions.
2 changes: 1 addition & 1 deletion cont/base/springcontent/gamedata/modrules.lua
Expand Up @@ -46,7 +46,7 @@ end


if (not (haveRules or haveSensors)) then
return false
return {}
end


Expand Down
22 changes: 14 additions & 8 deletions cont/base/springcontent/gamedata/sounds.lua
@@ -1,7 +1,10 @@
--- Valid entries used by engine: IncomingChat, MultiSelect, MapPoint
--- other than that, you can give it any name and access it like before with filenames
local Sounds = {
SoundItems = {
--[[
-- these four entries are played by the engine for corresponding events
-- the referenced .wav files are *not* supplied by base content, change
-- them if uncommenting an entry
-- any other name is free to use; sounds can also be referred to by file
IncomingChat = {
--- always play on the front speaker(s)
file = "sounds/beep4.wav",
Expand All @@ -13,12 +16,18 @@ local Sounds = {
in3d = "false",
},
MapPoint = {
--- respect where the point was set, but don't attuenuate in distace
--- also, when moving the camera, don't pitch it
--- respect where point was set, but don't attenuate over distance
--- also, when moving the camera, don't apply any pitch shift
file = "sounds/beep6.wav",
rolloff = 0,
dopplerscale = 0,
},
FailedCommand = {
file = "sounds/beep3.wav",
},
--]]
ExampleSound = {
--- some things you can do with this file
Expand All @@ -43,7 +52,7 @@ local Sounds = {
--- dopplerscale = 0 completely disables the effect
dopplerscale = 1,
--- when lots of sounds are played, sounds with lwoer priority are more likely to get cut off
--- when lots of sounds are played, sounds with lower priority are more likely to get cut off
--- priority > 0 will never be cut of (priorities can be negative)
priority = 0,
Expand All @@ -63,9 +72,6 @@ local Sounds = {
--- you can loop it for X miliseconds
looptime = 0,
},
FailedCommand = {
file = "sounds/beep3.wav",
},
default = {
--- new since 89.0
Expand Down
77 changes: 47 additions & 30 deletions rts/Lua/LuaParser.cpp
Expand Up @@ -24,6 +24,7 @@
#include "System/FileSystem/FileHandler.h"
#include "System/Misc/SpringTime.h"
#include "System/ContainerUtil.h"
#include "System/TimeProfiler.h"
#include "System/ScopedFPUSettings.h"
#include "System/StringUtil.h"

Expand Down Expand Up @@ -65,9 +66,7 @@ LuaParser::LuaParser(const std::string& _fileName, const std::string& _fileModes
}

LuaParser::LuaParser(const std::string& _textChunk, const std::string& _accessModes, const boolean& synced, const boolean& setup)
: fileName("")
, fileModes("")
, textChunk(_textChunk)
: textChunk(_textChunk)
, accessModes(_accessModes)

, D(false, false)
Expand Down Expand Up @@ -196,12 +195,11 @@ void LuaParser::SetupEnv(bool isSyncedCtxt, bool isDefsParser)
bool LuaParser::Execute()
{
if (!IsValid()) {
errorLog = "could not initialize LUA library";
errorLog = "could not initialize Lua library";
return false;
}

rootRef = LUA_NOREF;

assert(rootRef == LUA_NOREF);
assert(initDepth == 0);
initDepth = -1;

Expand All @@ -213,26 +211,30 @@ bool LuaParser::Execute()
codeLabel = "text chunk";
}
else if (!fileName.empty()) {
codeLabel = fileName;
CFileHandler fh(fileName, fileModes);
CFileHandler fh(codeLabel = fileName, fileModes);

if (!fh.LoadStringData(code)) {
errorLog = "could not open file: " + fileName;

LUA_CLOSE(&L);
return false;
}
}
else {
errorLog = "invalid format or empty file";

LUA_CLOSE(&L);
return false;
}

int error = luaL_loadbuffer(L, code.c_str(), code.size(), codeLabel.c_str());
char errorBuf[4096] = {0};
int errorNum = 0;

if (error != 0) {
errorLog = lua_tostring(L, -1);
LOG_L(L_ERROR, "%i, %s, %s", error, codeLabel.c_str(), errorLog.c_str());
if ((errorNum = luaL_loadbuffer(L, code.c_str(), code.size(), codeLabel.c_str())) != 0) {
SNPRINTF(errorBuf, sizeof(errorBuf), "[loadbuf] error %d (\"%s\") in %s", errorNum, lua_tostring(L, -1), codeLabel.c_str());
LUA_CLOSE(&L);

errorLog = errorBuf;
return false;
}

Expand All @@ -242,21 +244,33 @@ bool LuaParser::Execute()

// do not signal floating point exceptions in user Lua code
ScopedDisableFpuExceptions fe;
error = lua_pcall(L, 0, 1, 0);

if (error != 0) {
errorLog = lua_tostring(L, -1);
LOG_L(L_ERROR, "%i, %s, %s", error, fileName.c_str(), errorLog.c_str());
if ((errorNum = lua_pcall(L, 0, 1, 0)) != 0) {
SNPRINTF(errorBuf, sizeof(errorBuf), "[pcall] error %d (\"%s\") in %s", errorNum, lua_tostring(L, -1), fileName.c_str());
LUA_CLOSE(&L);

errorLog = errorBuf;
return false;
}

#if 0
if (!lua_istable(L, 1)) {
errorLog = "missing return table from " + fileName;
LOG_L(L_ERROR, "missing return table from %s", fileName.c_str());
errorLog = "no return table from " + fileName;

LUA_CLOSE(&L);
return false;
}
#else
// make not returning a table (which may or may not be intentional)
// equivalent to returning an empty one; leave it to callers whether
// they consider this an error
if (!lua_istable(L, 1)) {
lua_pop(L, lua_gettop(L));
lua_newtable(L);

errorLog = "no return table from " + fileName;
}
#endif

if (lowerKeys)
LuaUtils::LowerKeys(L, 1);
Expand All @@ -266,8 +280,8 @@ bool LuaParser::Execute()

rootRef = luaL_ref(L, LUA_REGISTRYINDEX);
lua_settop(L, 0);
valid = true;
return true;

return (valid = true);
}


Expand Down Expand Up @@ -473,24 +487,27 @@ void LuaParser::AddString(int key, const std::string& value)

int LuaParser::TimeCheck(lua_State* L)
{
#if (!defined(UNITSYNC) && !defined(DEDICATED))
if (!lua_isstring(L, 1) || !lua_isfunction(L, 2))
luaL_error(L, "Invalid arguments to TimeCheck('string', func, ...)");

const std::string name = lua_tostring(L, 1);
lua_remove(L, 1);
{
ScopedOnceTimer timer(lua_tostring(L, 1));

const spring_time startTime = spring_gettime();
lua_remove(L, 1);

if (lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0) != 0) {
const std::string errmsg = lua_tostring(L, -1);
lua_pop(L, 1);
luaL_error(L, errmsg.c_str());
}
if (lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0) != 0) {
const std::string errmsg = lua_tostring(L, -1);

const spring_time endTime = spring_gettime();
lua_pop(L, 1);
luaL_error(L, errmsg.c_str());
}
}

LOG("%s %ldms", name.c_str(), (long int) spring_tomsecs(endTime - startTime));
return lua_gettop(L);
#else
return 0;
#endif
}


Expand Down
3 changes: 2 additions & 1 deletion rts/Lua/LuaParser.h
Expand Up @@ -127,7 +127,8 @@ class LuaParser {
void SetupLua(bool isSyncedCtxt, bool isDefsParser);

bool Execute();
bool IsValid() const { return (L != nullptr); }
bool IsValid() const { return (L != nullptr); } // true if nothing failed during Execute
bool NoTable() const { return (errorLog.find("no return table") == 0); } // parser is still valid if true

LuaTable GetRoot();
LuaTable SubTableExpr(const std::string& expr) {
Expand Down
60 changes: 34 additions & 26 deletions rts/Lua/LuaUnsyncedCtrl.cpp
Expand Up @@ -529,46 +529,54 @@ int LuaUnsyncedCtrl::PlaySoundFile(lua_State* L)
}
}

// last argument (with and without pos/speed arguments) is the optional `sfx channel`
IAudioChannel** channel = &Channels::General;
// last argument (with and without pos/speed arguments) is the optional channel
IAudioChannel* channel = Channels::General;

if (args >= index) {
if (lua_isstring(L, index)) {
string channelStr = lua_tostring(L, index);
StringToLowerInPlace(channelStr);

if (channelStr == "battle" || channelStr == "sfx") {
channel = &Channels::Battle;
}
else if (channelStr == "unitreply" || channelStr == "voice") {
channel = &Channels::UnitReply;
}
else if (channelStr == "userinterface" || channelStr == "ui") {
channel = &Channels::UserInterface;
switch (hashString(lua_tostring(L, index))) {
case hashString("Battle"):
case hashString("battle"):
case hashString("SFX" ):
case hashString("sfx" ): {
channel = Channels::Battle;
} break;

case hashString("UnitReply"):
case hashString("unitreply"):
case hashString("Voice" ):
case hashString("voice" ): {
channel = Channels::UnitReply;
} break;

case hashString("UserInterface"):
case hashString("userinterface"):
case hashString("UI" ):
case hashString("ui" ): {
channel = Channels::UserInterface;
} break;

default: {
} break;
}
} else if (lua_isnumber(L, index)) {
const int channelNum = lua_toint(L, index);

if (channelNum == 1) {
channel = &Channels::Battle;
}
else if (channelNum == 2) {
channel = &Channels::UnitReply;
}
else if (channelNum == 3) {
channel = &Channels::UserInterface;
switch (lua_toint(L, index)) {
case 1: { channel = Channels::Battle ; } break;
case 2: { channel = Channels::UnitReply ; } break;
case 3: { channel = Channels::UserInterface; } break;
default: { } break;
}
}
}

if (index >= 6) {
if (index >= 9) {
channel[0]->PlaySample(soundID, pos, speed, volume);
channel->PlaySample(soundID, pos, speed, volume);
} else {
channel[0]->PlaySample(soundID, pos, volume);
channel->PlaySample(soundID, pos, volume);
}
} else
channel[0]->PlaySample(soundID, volume);
channel->PlaySample(soundID, volume);
}

if (!CLuaHandle::GetHandleSynced(L)) {
Expand Down
3 changes: 1 addition & 2 deletions rts/Sim/Misc/ModInfo.cpp
Expand Up @@ -100,7 +100,6 @@ void CModInfo::Init(const std::string& modFileName)
description = md.GetDescription();
}

// initialize the parser
LuaParser parser("gamedata/modrules.lua", SPRING_VFS_MOD_BASE, SPRING_VFS_ZIP);
// customize the defs environment
parser.GetTable("Spring");
Expand All @@ -109,7 +108,7 @@ void CModInfo::Init(const std::string& modFileName)
parser.Execute();

if (!parser.IsValid())
LOG_L(L_ERROR, "Failed loading mod-rules, using defaults; error: %s", parser.GetErrorLog().c_str());
LOG_L(L_ERROR, "[ModInfo::%s] error \"%s\" loading mod-rules, using defaults", __func__, parser.GetErrorLog().c_str());

const LuaTable& root = parser.GetRoot();

Expand Down

0 comments on commit 0b10bc8

Please sign in to comment.