Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKae <80987908+Novaenia@users.noreply.github.com>2023-07-19 01:16:22 +1000
committerKae <80987908+Novaenia@users.noreply.github.com>2023-07-19 01:16:22 +1000
commite1645f37fc72e7733b64c51ffbee0370e13cbe29 (patch)
treebdd219080958016e68589476004427cbb50616f5
parent770314fd7e86c0be355f19bd4273ebd12d5bcdc6 (diff)
Support for player entity message commands
-rw-r--r--assets/opensb/client.config.patch2
-rw-r--r--assets/opensb/player.config.patch1
-rw-r--r--assets/opensb/scripts/opensb/player/commands.lua30
-rw-r--r--assets/opensb/scripts/opensb/player/player.lua2
-rw-r--r--assets/opensb/scripts/opensb/universeclient/universeclient.lua2
-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.lua31
-rw-r--r--assets/opensb/scripts/universeClient/opensb.lua29
-rw-r--r--source/core/StarLua.cpp11
-rw-r--r--source/core/StarLua.hpp3
-rw-r--r--source/frontend/StarClientCommandProcessor.cpp55
-rw-r--r--source/frontend/StarClientCommandProcessor.hpp32
-rw-r--r--source/game/scripting/StarLuaRoot.cpp5
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);