diff options
-rw-r--r-- | assets/opensb/client.config.patch | 2 | ||||
-rw-r--r-- | assets/opensb/player.config.patch | 1 | ||||
-rw-r--r-- | assets/opensb/scripts/opensb/player/commands.lua | 30 | ||||
-rw-r--r-- | assets/opensb/scripts/opensb/player/player.lua | 2 | ||||
-rw-r--r-- | assets/opensb/scripts/opensb/universeclient/universeclient.lua | 2 | ||||
-rw-r--r-- | assets/opensb/scripts/opensb/universeclient/voicemanager.lua (renamed from assets/opensb/scripts/universeClient/opensb/voice_manager.lua) | 51 | ||||
-rw-r--r-- | assets/opensb/scripts/opensb/util/modules.lua | 31 | ||||
-rw-r--r-- | assets/opensb/scripts/universeClient/opensb.lua | 29 | ||||
-rw-r--r-- | source/core/StarLua.cpp | 11 | ||||
-rw-r--r-- | source/core/StarLua.hpp | 3 | ||||
-rw-r--r-- | source/frontend/StarClientCommandProcessor.cpp | 55 | ||||
-rw-r--r-- | source/frontend/StarClientCommandProcessor.hpp | 32 | ||||
-rw-r--r-- | source/game/scripting/StarLuaRoot.cpp | 5 |
13 files changed, 155 insertions, 99 deletions
diff --git a/assets/opensb/client.config.patch b/assets/opensb/client.config.patch index e0d5687..a0de983 100644 --- a/assets/opensb/client.config.patch +++ b/assets/opensb/client.config.patch @@ -1,5 +1,5 @@ { - "universeScriptContexts" : { "opensb" : ["/scripts/universeClient/opensb.lua"] }, + "universeScriptContexts" : { "OpenStarbound" : ["/scripts/opensb/universeclient/universeclient.lua"] }, // Disables scissoring and letterboxing on vanilla and modded warp cinematics "warpCinematicBase" : { diff --git a/assets/opensb/player.config.patch b/assets/opensb/player.config.patch index 88bc330..3daa696 100644 --- a/assets/opensb/player.config.patch +++ b/assets/opensb/player.config.patch @@ -1,4 +1,5 @@ { + "genericScriptContexts" : { "OpenStarbound" : "/scripts/opensb/player/player.lua" }, "wireConfig" : { "innerBrightnessScale" : 20, "firstStripeThickness" : 0.6, diff --git a/assets/opensb/scripts/opensb/player/commands.lua b/assets/opensb/scripts/opensb/player/commands.lua new file mode 100644 index 0000000..f62e2b8 --- /dev/null +++ b/assets/opensb/scripts/opensb/player/commands.lua @@ -0,0 +1,30 @@ +local module = {} +modules.commands = module + +local commands = {} +local function command(name, func) + commands[name] = func +end + +function module.init() + for name, func in pairs(commands) do + message.setHandler("/" .. name, function(isLocal, _, ...) + if not isLocal then + return + else + return func(...) + end + end) + end +end + + +command("run", function(src) + local success, result = pcall(loadstring, src, "/run") + if not success then + return "^#f00;compile error: " .. result + else + local success, result = pcall(result) + return not success and "^#f00;error: " .. result or sb.printJson(result) + end +end)
\ No newline at end of file diff --git a/assets/opensb/scripts/opensb/player/player.lua b/assets/opensb/scripts/opensb/player/player.lua new file mode 100644 index 0000000..05cbfb9 --- /dev/null +++ b/assets/opensb/scripts/opensb/player/player.lua @@ -0,0 +1,2 @@ +require "/scripts/opensb/util/modules.lua" +modules("/scripts/opensb/player/", {"commands"})
\ No newline at end of file diff --git a/assets/opensb/scripts/opensb/universeclient/universeclient.lua b/assets/opensb/scripts/opensb/universeclient/universeclient.lua new file mode 100644 index 0000000..cad342b --- /dev/null +++ b/assets/opensb/scripts/opensb/universeclient/universeclient.lua @@ -0,0 +1,2 @@ +require "/scripts/opensb/util/modules.lua" +modules("/scripts/opensb/universeclient/", {"voicemanager"})
\ No newline at end of file diff --git a/assets/opensb/scripts/universeClient/opensb/voice_manager.lua b/assets/opensb/scripts/opensb/universeclient/voicemanager.lua index d1c540f..c0aa309 100644 --- a/assets/opensb/scripts/universeClient/opensb/voice_manager.lua +++ b/assets/opensb/scripts/opensb/universeclient/voicemanager.lua @@ -4,7 +4,7 @@ local fmt = string.format local sqrt = math.sqrt local module = {} -submodules.voice_manager = module +modules.voice_manager = module --constants local INDICATOR_PATH = "/interface/voicechat/indicator/" @@ -19,52 +19,35 @@ local LINE_COLOR = {50, 210, 255, 255} local FONT_DIRECTIVES = "?border=1;333;3337?border=1;333;3330" local NAME_PREFIX = "^noshadow,white,set;" -local canvas - -local linePaddingDrawable = { - image = BACK_INDICATOR_IMAGE, - position = {0, 0}, - color = LINE_COLOR, - centered = false -} - -local function getLinePadding(a, b) - linePaddingDrawable.image = BACK_INDICATOR_IMAGE .. fmt("?crop=%i;%i;%i;%i?fade=fff;1", a, 0, b, INDICATOR_SIZE[2]) - linePaddingDrawable.position[1] = a - return linePaddingDrawable; +local linePaddingDrawable +do + local drawable = { image = BACK_INDICATOR_IMAGE, position = {0, 0}, color = LINE_COLOR, centered = false } + function linePaddingDrawable(a, b) + drawable.image = BACK_INDICATOR_IMAGE .. fmt("?crop=%i;%i;%i;%i?fade=fff;1", a, 0, b, INDICATOR_SIZE[2]) + drawable.position[1] = a + return drawable; + end end -local lineDrawable = { - line = {{LINE_PADDING, 24}, {10, 24}}, - width = 48, - color = LINE_COLOR -} - -local function drawTheLine(pos, value) +local function line(pos, value) local width = math.floor((LINE_WIDTH * value) + 0.5) LINE_COLOR[4] = 255 * math.min(1, sqrt(width / 350)) if width > 0 then - canvas:drawDrawable(getLinePadding(0, math.min(12, width)), pos) + canvas:drawDrawable(linePaddingDrawable(0, math.min(12, width)), pos) if width > 12 then lineDrawable.line[2][1] = math.min(width, LINE_WIDTH_PADDED) canvas:drawDrawable(lineDrawable, pos) if width > LINE_WIDTH_PADDED then - canvas:drawDrawable(getLinePadding(LINE_WIDTH_PADDED, width), pos) + canvas:drawDrawable(linePaddingDrawable(LINE_WIDTH_PADDED, width), pos) end end end end -local drawable = { - image = BACK_INDICATOR_IMAGE, - centered = false -} +local canvas -local textPositioning = { - position = {0, 0}, - horizontalAnchor = "left", - verticalAnchor = "mid" -} +local drawable = { image = BACK_INDICATOR_IMAGE, centered = false } +local textPositioning = { position = {0, 0}, horizontalAnchor = "left", verticalAnchor = "mid" } local hoveredSpeaker = nil local hoveredSpeakerIndex = 1 @@ -78,7 +61,7 @@ end local function drawSpeakerBar(mouse, pos, speaker, i) drawable.image = BACK_INDICATOR_IMAGE canvas:drawDrawable(drawable, pos) - drawTheLine(pos, 1 - math.sqrt(math.min(1, math.max(0, speaker.loudness / -50)))) + line(pos, 1 - sqrt(math.min(1, math.max(0, speaker.loudness / -50)))) local hovering = not speaker.isLocal and mouseOverSpeaker(mouse, pos) textPositioning.position = {pos[1] + 49, pos[2] + 24} @@ -128,7 +111,6 @@ local function drawIndicators() local mousePosition = canvas:mousePosition() local basePos = {screenSize[1] - 350, 50} - -- sort it ourselves for now local speakersRemaining, speakers = {}, {} local hoveredSpeakerId = nil if hoveredSpeaker then @@ -140,7 +122,6 @@ local function drawIndicators() end local speakerCount = 0 - local now = os.clock() for i, speaker in pairs(voice.speakers()) do local speakerId = speaker.speakerId speakersRemaining[speakerId] = true diff --git a/assets/opensb/scripts/opensb/util/modules.lua b/assets/opensb/scripts/opensb/util/modules.lua new file mode 100644 index 0000000..2ce7086 --- /dev/null +++ b/assets/opensb/scripts/opensb/util/modules.lua @@ -0,0 +1,31 @@ +modules = setmetatable({}, {__call = function(this, path, names) + for i, name in pairs(names) do + require(path .. name .. ".lua") + end +end}) + +local modules, type = modules, type +local function call(func, ...) + if type(func) == "function" then + return func(...) + end +end + +function init(...) + script.setUpdateDelta(1) + for i, module in pairs(modules) do + call(module.init, ...) + end +end + +function update(...) + for i, module in pairs(modules) do + call(module.update, ...) + end +end + +function uninit(...) + for i, module in pairs(modules) do + call(module.uninit, ...) + end +end
\ No newline at end of file diff --git a/assets/opensb/scripts/universeClient/opensb.lua b/assets/opensb/scripts/universeClient/opensb.lua deleted file mode 100644 index c1b4dea..0000000 --- a/assets/opensb/scripts/universeClient/opensb.lua +++ /dev/null @@ -1,29 +0,0 @@ -submodules = {} - -require "/scripts/universeClient/opensb/voice_manager.lua" - -local submodules, type = submodules, type -local function call(func, ...) - if type(func) == "function" then - return func(...) - end -end - -function init(...) - script.setUpdateDelta(1) - for i, module in pairs(submodules) do - call(module.init, ...) - end -end - -function update(...) - for i, module in pairs(submodules) do - call(module.update, ...) - end -end - -function uninit(...) - for i, module in pairs(submodules) do - call(module.uninit, ...) - end -end
\ No newline at end of file diff --git a/source/core/StarLua.cpp b/source/core/StarLua.cpp index 4e89097..287bf5c 100644 --- a/source/core/StarLua.cpp +++ b/source/core/StarLua.cpp @@ -1095,6 +1095,17 @@ LuaFunction LuaEngine::createRawFunction(lua_CFunction function) { return LuaFunction(LuaDetail::LuaHandle(RefPtr<LuaEngine>(this), popHandle(m_state))); } +LuaFunction LuaEngine::createFunctionFromSource(int handleIndex, char const* contents, size_t size, char const* name) { + lua_checkstack(m_state, 2); + + handleError(m_state, luaL_loadbuffer(m_state, contents, size, name)); + + pushHandle(m_state, handleIndex); + lua_setupvalue(m_state, -2, 1); + + return LuaFunction(LuaDetail::LuaHandle(RefPtr<LuaEngine>(this), popHandle(m_state))); +} + void LuaEngine::pushLuaValue(lua_State* state, LuaValue const& luaValue) { lua_checkstack(state, 1); diff --git a/source/core/StarLua.hpp b/source/core/StarLua.hpp index 500923d..dda0802 100644 --- a/source/core/StarLua.hpp +++ b/source/core/StarLua.hpp @@ -310,6 +310,7 @@ public: using LuaTable::contains; using LuaTable::remove; using LuaTable::engine; + using LuaTable::handleIndex; // Splits the path by '.' character, so can get / set values in tables inside // other tables. If any table in the path is not a table but is accessed as @@ -530,6 +531,8 @@ public: LuaFunction createRawFunction(lua_CFunction func); + LuaFunction createFunctionFromSource(int handleIndex, char const* contents, size_t size, char const* name); + LuaThread createThread(); template <typename T> diff --git a/source/frontend/StarClientCommandProcessor.cpp b/source/frontend/StarClientCommandProcessor.cpp index 7b6e234..ec5b27c 100644 --- a/source/frontend/StarClientCommandProcessor.cpp +++ b/source/frontend/StarClientCommandProcessor.cpp @@ -10,6 +10,7 @@ #include "StarAiInterface.hpp" #include "StarQuestInterface.hpp" #include "StarStatistics.hpp" +#include "StarInterfaceLuaBindings.hpp" namespace Star { @@ -76,11 +77,10 @@ StringList ClientCommandProcessor::handleCommand(String const& commandLine) { String allArguments = commandLine.substr(1); String command = allArguments.extract(); - auto arguments = m_parser.tokenizeToStringList(allArguments); StringList result; if (auto builtinCommand = m_builtinCommands.maybe(command)) { - result.append((*builtinCommand)(arguments)); + result.append((*builtinCommand)(allArguments)); } else if (auto macroCommand = m_macroCommands.maybe(command)) { for (auto const& c : *macroCommand) { if (c.beginsWith("/")) @@ -89,7 +89,11 @@ StringList ClientCommandProcessor::handleCommand(String const& commandLine) { result.append(c); } } else { - m_universeClient->sendChat(commandLine, ChatSendMode::Broadcast); + auto player = m_universeClient->mainPlayer(); + if (auto messageResult = player->receiveMessage(connectionForEntity(player->entityId()), strf("/{}", command), { allArguments })) + result.append(messageResult->isType(Json::Type::String) ? *messageResult->stringPtr() : messageResult->repr(1, true)); + else + m_universeClient->sendChat(commandLine, ChatSendMode::Broadcast); } return result; } catch (ShellParsingException const& e) { @@ -130,7 +134,8 @@ String ClientCommandProcessor::gravity() { return toString(m_universeClient->worldClient()->gravity(m_universeClient->mainPlayer()->position())); } -String ClientCommandProcessor::debug(StringList const& arguments) { +String ClientCommandProcessor::debug(String const& argumentsString) { + auto arguments = m_parser.tokenizeToStringList(argumentsString); if (!adminCommandAllowed()) return "You must be an admin to use this command."; @@ -168,7 +173,8 @@ String ClientCommandProcessor::asyncLighting() { ? "enabled" : "disabled"); } -String ClientCommandProcessor::setGravity(StringList const& arguments) { +String ClientCommandProcessor::setGravity(String const& argumentsString) { + auto arguments = m_parser.tokenizeToStringList(argumentsString); if (!adminCommandAllowed()) return "You must be an admin to use this command."; @@ -198,7 +204,8 @@ String ClientCommandProcessor::monochromeLighting() { return strf("Monochrome lighting {}", monochrome ? "enabled" : "disabled"); } -String ClientCommandProcessor::radioMessage(StringList const& arguments) { +String ClientCommandProcessor::radioMessage(String const& argumentsString) { + auto arguments = m_parser.tokenizeToStringList(argumentsString); if (!adminCommandAllowed()) return "You must be an admin to use this command."; @@ -225,7 +232,8 @@ String ClientCommandProcessor::clearCinematics() { return "Player cinematic records cleared!"; } -String ClientCommandProcessor::startQuest(StringList const& arguments) { +String ClientCommandProcessor::startQuest(String const& argumentsString) { + auto arguments = m_parser.tokenizeToStringList(argumentsString); if (!adminCommandAllowed()) return "You must be an admin to use this command."; @@ -234,7 +242,8 @@ String ClientCommandProcessor::startQuest(StringList const& arguments) { return "Quest started"; } -String ClientCommandProcessor::completeQuest(StringList const& arguments) { +String ClientCommandProcessor::completeQuest(String const& argumentsString) { + auto arguments = m_parser.tokenizeToStringList(argumentsString); if (!adminCommandAllowed()) return "You must be an admin to use this command."; @@ -242,7 +251,8 @@ String ClientCommandProcessor::completeQuest(StringList const& arguments) { return strf("Quest {} complete", arguments.at(0)); } -String ClientCommandProcessor::failQuest(StringList const& arguments) { +String ClientCommandProcessor::failQuest(String const& argumentsString) { + auto arguments = m_parser.tokenizeToStringList(argumentsString); if (!adminCommandAllowed()) return "You must be an admin to use this command."; @@ -250,7 +260,8 @@ String ClientCommandProcessor::failQuest(StringList const& arguments) { return strf("Quest {} failed", arguments.at(0)); } -String ClientCommandProcessor::previewNewQuest(StringList const& arguments) { +String ClientCommandProcessor::previewNewQuest(String const& argumentsString) { + auto arguments = m_parser.tokenizeToStringList(argumentsString); if (!adminCommandAllowed()) return "You must be an admin to use this command."; @@ -259,7 +270,8 @@ String ClientCommandProcessor::previewNewQuest(StringList const& arguments) { }); } -String ClientCommandProcessor::previewQuestComplete(StringList const& arguments) { +String ClientCommandProcessor::previewQuestComplete(String const& argumentsString) { + auto arguments = m_parser.tokenizeToStringList(argumentsString); if (!adminCommandAllowed()) return "You must be an admin to use this command."; @@ -268,7 +280,8 @@ String ClientCommandProcessor::previewQuestComplete(StringList const& arguments) }); } -String ClientCommandProcessor::previewQuestFailed(StringList const& arguments) { +String ClientCommandProcessor::previewQuestFailed(String const& argumentsString) { + auto arguments = m_parser.tokenizeToStringList(argumentsString); if (!adminCommandAllowed()) return "You must be an admin to use this command."; @@ -294,7 +307,8 @@ String ClientCommandProcessor::deathCount() { return strf("Total deaths: {}{}", deaths, deaths == 0 ? ". Well done!" : ""); } -String ClientCommandProcessor::cinema(StringList const& arguments) { +String ClientCommandProcessor::cinema(String const& argumentsString) { + auto arguments = m_parser.tokenizeToStringList(argumentsString); if (!adminCommandAllowed()) return "You must be an admin to use this command."; @@ -326,7 +340,8 @@ String ClientCommandProcessor::resetAchievements() { return "Unable to reset achievements"; } -String ClientCommandProcessor::statistic(StringList const& arguments) { +String ClientCommandProcessor::statistic(String const& argumentsString) { + auto arguments = m_parser.tokenizeToStringList(argumentsString); if (!adminCommandAllowed()) return "You must be an admin to use this command."; @@ -337,7 +352,8 @@ String ClientCommandProcessor::statistic(StringList const& arguments) { return values.join("\n"); } -String ClientCommandProcessor::giveEssentialItem(StringList const& arguments) { +String ClientCommandProcessor::giveEssentialItem(String const& argumentsString) { + auto arguments = m_parser.tokenizeToStringList(argumentsString); if (!adminCommandAllowed()) return "You must be an admin to use this command."; @@ -354,7 +370,8 @@ String ClientCommandProcessor::giveEssentialItem(StringList const& arguments) { } } -String ClientCommandProcessor::makeTechAvailable(StringList const& arguments) { +String ClientCommandProcessor::makeTechAvailable(String const& argumentsString) { + auto arguments = m_parser.tokenizeToStringList(argumentsString); if (!adminCommandAllowed()) return "You must be an admin to use this command."; @@ -365,7 +382,8 @@ String ClientCommandProcessor::makeTechAvailable(StringList const& arguments) { return strf("Added {} to player's visible techs", arguments.at(0)); } -String ClientCommandProcessor::enableTech(StringList const& arguments) { +String ClientCommandProcessor::enableTech(String const& argumentsString) { + auto arguments = m_parser.tokenizeToStringList(argumentsString); if (!adminCommandAllowed()) return "You must be an admin to use this command."; @@ -377,7 +395,8 @@ String ClientCommandProcessor::enableTech(StringList const& arguments) { return strf("Player tech {} enabled", arguments.at(0)); } -String ClientCommandProcessor::upgradeShip(StringList const& arguments) { +String ClientCommandProcessor::upgradeShip(String const& argumentsString) { + auto arguments = m_parser.tokenizeToStringList(argumentsString); if (!adminCommandAllowed()) return "You must be an admin to use this command."; diff --git a/source/frontend/StarClientCommandProcessor.hpp b/source/frontend/StarClientCommandProcessor.hpp index 41809ed..e9e8962 100644 --- a/source/frontend/StarClientCommandProcessor.hpp +++ b/source/frontend/StarClientCommandProcessor.hpp @@ -29,40 +29,40 @@ private: String reload(); String whoami(); String gravity(); - String debug(StringList const& arguments); + String debug(String const& argumentsString); String boxes(); String fullbright(); String asyncLighting(); - String setGravity(StringList const& arguments); + String setGravity(String const& argumentsString); String resetGravity(); String fixedCamera(); String monochromeLighting(); - String radioMessage(StringList const& arguments); + String radioMessage(String const& argumentsString); String clearRadioMessages(); String clearCinematics(); - String startQuest(StringList const& arguments); - String completeQuest(StringList const& arguments); - String failQuest(StringList const& arguments); - String previewNewQuest(StringList const& arguments); - String previewQuestComplete(StringList const& arguments); - String previewQuestFailed(StringList const& arguments); + String startQuest(String const& argumentsString); + String completeQuest(String const& argumentsString); + String failQuest(String const& argumentsString); + String previewNewQuest(String const& argumentsString); + String previewQuestComplete(String const& argumentsString); + String previewQuestFailed(String const& argumentsString); String clearScannedObjects(); String playTime(); String deathCount(); - String cinema(StringList const& arguments); + String cinema(String const& argumentsString); String suicide(); String naked(); String resetAchievements(); - String statistic(StringList const& arguments); - String giveEssentialItem(StringList const& arguments); - String makeTechAvailable(StringList const& arguments); - String enableTech(StringList const& arguments); - String upgradeShip(StringList const& arguments); + String statistic(String const& argumentsString); + String giveEssentialItem(String const& argumentsString); + String makeTechAvailable(String const& argumentsString); + String enableTech(String const& argumentsString); + String upgradeShip(String const& argumentsString); UniverseClientPtr m_universeClient; CinematicPtr m_cinematicOverlay; MainInterfacePaneManager* m_paneManager; - CaseInsensitiveStringMap<function<String(StringList const&)>> m_builtinCommands; + CaseInsensitiveStringMap<function<String(String const&)>> m_builtinCommands; StringMap<StringList> m_macroCommands; ShellParser m_parser; LuaBaseComponent m_scriptComponent; diff --git a/source/game/scripting/StarLuaRoot.cpp b/source/game/scripting/StarLuaRoot.cpp index d41e8fc..5aa0284 100644 --- a/source/game/scripting/StarLuaRoot.cpp +++ b/source/game/scripting/StarLuaRoot.cpp @@ -106,6 +106,11 @@ LuaContext LuaRoot::createContext(StringList const& scriptPaths) { } }); + newContext.set("loadstring", m_luaEngine->createFunction([newContext](String const& source, Maybe<String> const& name, Maybe<LuaValue> const& env) -> LuaFunction { + String functionName = name ? strf("loadstring: {}", name) : "loadstring"; + return newContext.engine().createFunctionFromSource(newContext.handleIndex(), source.utf8Ptr(), source.utf8Size(), functionName.utf8Ptr()); + })); + for (auto const& scriptPath : scriptPaths) cache->loadContextScript(newContext, scriptPath); |