Support for player entity message commands
This commit is contained in:
parent
770314fd7e
commit
e1645f37fc
@ -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" : {
|
||||
|
@ -1,4 +1,5 @@
|
||||
{
|
||||
"genericScriptContexts" : { "OpenStarbound" : "/scripts/opensb/player/player.lua" },
|
||||
"wireConfig" : {
|
||||
"innerBrightnessScale" : 20,
|
||||
"firstStripeThickness" : 0.6,
|
||||
|
30
assets/opensb/scripts/opensb/player/commands.lua
Normal file
30
assets/opensb/scripts/opensb/player/commands.lua
Normal file
@ -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)
|
2
assets/opensb/scripts/opensb/player/player.lua
Normal file
2
assets/opensb/scripts/opensb/player/player.lua
Normal file
@ -0,0 +1,2 @@
|
||||
require "/scripts/opensb/util/modules.lua"
|
||||
modules("/scripts/opensb/player/", {"commands"})
|
@ -0,0 +1,2 @@
|
||||
require "/scripts/opensb/util/modules.lua"
|
||||
modules("/scripts/opensb/universeclient/", {"voicemanager"})
|
@ -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
|
@ -1,8 +1,10 @@
|
||||
submodules = {}
|
||||
modules = setmetatable({}, {__call = function(this, path, names)
|
||||
for i, name in pairs(names) do
|
||||
require(path .. name .. ".lua")
|
||||
end
|
||||
end})
|
||||
|
||||
require "/scripts/universeClient/opensb/voice_manager.lua"
|
||||
|
||||
local submodules, type = submodules, type
|
||||
local modules, type = modules, type
|
||||
local function call(func, ...)
|
||||
if type(func) == "function" then
|
||||
return func(...)
|
||||
@ -11,19 +13,19 @@ end
|
||||
|
||||
function init(...)
|
||||
script.setUpdateDelta(1)
|
||||
for i, module in pairs(submodules) do
|
||||
for i, module in pairs(modules) do
|
||||
call(module.init, ...)
|
||||
end
|
||||
end
|
||||
|
||||
function update(...)
|
||||
for i, module in pairs(submodules) do
|
||||
for i, module in pairs(modules) do
|
||||
call(module.update, ...)
|
||||
end
|
||||
end
|
||||
|
||||
function uninit(...)
|
||||
for i, module in pairs(submodules) do
|
||||
for i, module in pairs(modules) do
|
||||
call(module.uninit, ...)
|
||||
end
|
||||
end
|
@ -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);
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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,6 +89,10 @@ StringList ClientCommandProcessor::handleCommand(String const& commandLine) {
|
||||
result.append(c);
|
||||
}
|
||||
} else {
|
||||
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;
|
||||
@ -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.";
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user