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

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/build.yml5
-rw-r--r--assets/opensb/interface/opensb/shaders/shaders.lua21
-rw-r--r--assets/opensb/interface/windowconfig/multiplayer.config.patch22
-rw-r--r--assets/opensb/scripts/opensb/universeclient/loadconfig.lua14
-rw-r--r--doc/lua/openstarbound/chat.md59
-rw-r--r--source/base/StarAssets.cpp6
-rw-r--r--source/base/StarAssets.hpp2
-rw-r--r--source/client/StarClientApplication.cpp28
-rw-r--r--source/client/StarClientApplication.hpp7
-rw-r--r--source/client/StarRenderingLuaBindings.cpp3
-rw-r--r--source/core/StarDataStream.cpp2
-rw-r--r--source/core/StarLua.hpp3
-rw-r--r--source/core/StarNetCompatibility.cpp2
-rw-r--r--source/core/StarVersion.cpp.in1
-rw-r--r--source/core/StarVersion.hpp1
-rw-r--r--source/frontend/StarCharSelection.cpp2
-rw-r--r--source/frontend/StarInterfaceLuaBindings.cpp4
-rw-r--r--source/frontend/StarTitleScreen.cpp17
-rw-r--r--source/frontend/StarTitleScreen.hpp4
-rw-r--r--source/game/CMakeLists.txt2
-rw-r--r--source/game/StarChatProcessor.cpp18
-rw-r--r--source/game/StarChatProcessor.hpp6
-rw-r--r--source/game/StarChatTypes.cpp10
-rw-r--r--source/game/StarChatTypes.hpp2
-rw-r--r--source/game/StarItemBag.cpp17
-rw-r--r--source/game/StarItemBag.hpp1
-rw-r--r--source/game/StarMonster.cpp2
-rw-r--r--source/game/StarNetPackets.cpp6
-rw-r--r--source/game/StarNetPackets.hpp2
-rw-r--r--source/game/StarNpc.cpp27
-rw-r--r--source/game/StarNpc.hpp3
-rw-r--r--source/game/StarPlayer.cpp5
-rw-r--r--source/game/StarPlayerStorage.cpp2
-rw-r--r--source/game/StarSkyParameters.cpp2
-rw-r--r--source/game/StarSongbook.cpp18
-rw-r--r--source/game/StarSongbook.hpp12
-rw-r--r--source/game/StarStagehand.cpp2
-rw-r--r--source/game/StarUniverseClient.cpp19
-rw-r--r--source/game/StarUniverseClient.hpp4
-rw-r--r--source/game/StarUniverseServer.cpp17
-rw-r--r--source/game/StarUniverseServer.hpp2
-rw-r--r--source/game/scripting/StarBehaviorLuaBindings.cpp2
-rw-r--r--source/game/scripting/StarBehaviorLuaBindings.hpp2
-rwxr-xr-x[-rw-r--r--]source/game/scripting/StarPlayerLuaBindings.cpp11
-rw-r--r--source/game/scripting/StarRootLuaBindings.cpp17
-rw-r--r--source/game/scripting/StarScriptableThread.cpp6
-rw-r--r--source/game/scripting/StarSongbookLuaBindings.cpp21
-rw-r--r--source/game/scripting/StarSongbookLuaBindings.hpp11
-rw-r--r--source/server/main.cpp2
49 files changed, 364 insertions, 90 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 51c223f..6474e7e 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -26,6 +26,11 @@ on:
- '*'
pull_request:
+ paths:
+ - 'assets/**'
+ - 'source/**'
+ - 'toolchains/**'
+ - 'triplets/**'
branches:
- '*'
diff --git a/assets/opensb/interface/opensb/shaders/shaders.lua b/assets/opensb/interface/opensb/shaders/shaders.lua
index f9b6a32..befbabf 100644
--- a/assets/opensb/interface/opensb/shaders/shaders.lua
+++ b/assets/opensb/interface/opensb/shaders/shaders.lua
@@ -184,6 +184,18 @@ local function addOption(data, i, added)
end
end
+local function updateParameter(parameter,oname,value)
+ if parameter.isPasses then
+ for k,v in next, parameter.layers do
+ renderer.setPostProcessLayerPasses(v, value)
+ end
+ else
+ for k,v in next, parameter.effects do
+ renderer.setEffectParameter(v, oname, value)
+ end
+ end
+end
+
function sliderOptionModified(option, odata)
local oname = string.sub(option, optionOffset)
local parameter = groups[activeGroup].parameters[oname]
@@ -191,15 +203,12 @@ function sliderOptionModified(option, odata)
widget.setText(fmt("%s.%s",OPTIONS_WIDGET,option.."_value"), fmt(digitRegex(parameter.delta),value))
- for k,v in next, parameter.effects do
- renderer.setEffectParameter(v, oname, value)
- end
+ updateParameter(parameter,oname,value)
shaderConfig[activeGroup].parameters[oname] = value
root.setConfiguration("postProcessGroups",shaderConfig)
end
function selectOptionPressed(button,bdata)
- sb.logInfo(sb.print(bdata))
for k,v in next, bdata.buttons do
if v.index ~= bdata.index then
@@ -212,9 +221,7 @@ function selectOptionPressed(button,bdata)
local oname = bdata.option.name
local parameter = groups[activeGroup].parameters[oname]
- for k,v in next, parameter.effects do
- renderer.setEffectParameter(v, oname, value)
- end
+ updateParameter(parameter,oname,value)
shaderConfig[activeGroup].parameters[oname] = value
root.setConfiguration("postProcessGroups",shaderConfig)
end
diff --git a/assets/opensb/interface/windowconfig/multiplayer.config.patch b/assets/opensb/interface/windowconfig/multiplayer.config.patch
index 8bd27c1..bfd6297 100644
--- a/assets/opensb/interface/windowconfig/multiplayer.config.patch
+++ b/assets/opensb/interface/windowconfig/multiplayer.config.patch
@@ -4,5 +4,25 @@
"anchor" : "center",
"positionLocked" : true
},
+ "connect": {
+ "position" : [34, 32]
+ },
+ "legacyLabel" : {
+ "type" : "label",
+ "position" : [130, 34],
+ "hAnchor" : "left",
+ "value" : "FORCE LEGACY"
+ },
+ "legacyCheckbox" : {
+ "type" : "button",
+ "pressedOffset" : [0, 0],
+ "position" : [120, 34],
+ "base" : "/interface/optionsmenu/checkboxnocheck.png",
+ "hover" : "/interface/optionsmenu/checkboxnocheckhover.png",
+ "baseImageChecked" : "/interface/optionsmenu/checkboxcheck.png",
+ "hoverImageChecked" : "/interface/optionsmenu/checkboxcheckhover.png",
+ "checkable" : true,
+ "checked": false
+ },
"password" : { "hidden" : true }
-} \ No newline at end of file
+}
diff --git a/assets/opensb/scripts/opensb/universeclient/loadconfig.lua b/assets/opensb/scripts/opensb/universeclient/loadconfig.lua
index c0fc845..0898bc0 100644
--- a/assets/opensb/scripts/opensb/universeclient/loadconfig.lua
+++ b/assets/opensb/scripts/opensb/universeclient/loadconfig.lua
@@ -11,9 +11,17 @@ function module.init()
local group = postProcessGroups[k]
if group and v.parameters then
for k2,v2 in next, group.parameters do
- if v.parameters[k2] ~= nil then
- for _,e in next, v2.effects do
- renderer.setEffectParameter(e,k2,v.parameters[k2])
+ local param = v.parameters[k2]
+ if param ~= nil then
+ if v2.isPasses then
+ -- this parameter controls passes
+ for _,l in next, v2.layers do
+ renderer.setPostProcessLayerPasses(l,param)
+ end
+ else
+ for _,e in next, v2.effects do
+ renderer.setEffectParameter(e,k2,param)
+ end
end
end
end
diff --git a/doc/lua/openstarbound/chat.md b/doc/lua/openstarbound/chat.md
new file mode 100644
index 0000000..af9c96d
--- /dev/null
+++ b/doc/lua/openstarbound/chat.md
@@ -0,0 +1,59 @@
+# Chat
+
+The new chat table is accessible from almost every clientside script and allows interaction with the in-game chat system.
+
+---
+
+#### `double` chat.send(`String` message, [`String` modeName], [`bool` speak], [`Json` data]))
+
+Sends a new message in the chat. Optionally specifies the modeName:
+
+- `"Broadcast"`: Global chat. Default value.
+- `"Local"`: Chat within the current planet.
+- `"Party"`: Chat within the current party.
+
+If `speak` is false, the chat bubble will not appear above the player.
+If `data` is provided, it will be sent as a JSON object with the message. This can be used to send custom data with the message.
+
+---
+
+#### `String[]` chat.command(`String` command)
+
+Executes the specified command and returns a list of strings with the result.
+
+---
+
+#### `void` chat.addMessage(`String` text, [`Json` config])
+
+Adds the specified message to the chat log. The following keys are available in the `config` JSON object:
+
+- `String` __mode__ - The mode of the message. Can be one of the followgin:
+ - `"Broadcast"`
+ - `"Local"`
+ - `"Party"`
+ - `"Whisper"`
+ - `"CommandResult"`
+ - `"RadioMessage"`
+ - `"World"`
+- `String` __channelName__ - The name of the channel to send the message to.
+- `String` __fromNick__ - The name of the sender of the message.
+- `String` __portrait__ - message portrait.
+- `bool` __showPane__ - If false, the chat pane will not be triggered.
+
+---
+
+#### `String` chat.input()
+
+Returns the current chat input text.
+
+---
+
+#### `bool` chat.setInput(`String` text, [`bool` moveCursor])
+
+Sets the current chat input text. If `moveCursor` is true, the cursor will be moved to the end of the text. Returns true if the input was set successfully, false otherwise.
+
+---
+
+#### `void` chat.clear([`unsigned`] count)
+
+Clears the chat input text. If `count` is provided, it will clear the last `count` messages, all otherwise. \ No newline at end of file
diff --git a/source/base/StarAssets.cpp b/source/base/StarAssets.cpp
index 9742f9e..b6aeab9 100644
--- a/source/base/StarAssets.cpp
+++ b/source/base/StarAssets.cpp
@@ -969,8 +969,9 @@ ImageConstPtr Assets::readImage(String const& path) const {
auto& patchSource = pair.second;
auto patchStream = patchSource->read(patchPath);
if (patchPath.endsWith(".lua")) {
+ std::pair<AssetSource*, String> contextKey = make_pair(patchSource.get(), patchPath);
luaLocker.lock();
- LuaContextPtr& context = m_patchContexts[patchPath];
+ LuaContextPtr& context = m_patchContexts[contextKey];
if (!context) {
context = make_shared<LuaContext>(luaEngine->createContext());
context->load(patchStream, patchPath);
@@ -1042,9 +1043,10 @@ Json Assets::readJson(String const& path) const {
auto& patchSource = pair.second;
auto patchStream = patchSource->read(patchBasePath);
if (patchBasePath.endsWith(".lua")) {
+ std::pair<AssetSource*, String> contextKey = make_pair(patchSource.get(), patchBasePath);
RecursiveMutexLocker luaLocker(m_luaMutex);
// Kae: i don't like that lock. perhaps have a LuaEngine and patch context cache per worker thread later on?
- LuaContextPtr& context = m_patchContexts[patchBasePath];
+ LuaContextPtr& context = m_patchContexts[contextKey];
if (!context) {
context = make_shared<LuaContext>(as<LuaEngine>(m_luaEngine.get())->createContext());
context->load(patchStream, patchBasePath);
diff --git a/source/base/StarAssets.hpp b/source/base/StarAssets.hpp
index a8e4480..6cc8c16 100644
--- a/source/base/StarAssets.hpp
+++ b/source/base/StarAssets.hpp
@@ -331,7 +331,7 @@ private:
// Lua
RefPtr<RefCounter> m_luaEngine; // dumb but to avoid including Lua.hpp in here...
- mutable StringMap<LuaContextPtr> m_patchContexts;
+ mutable HashMap<pair<AssetSource*, String>, LuaContextPtr> m_patchContexts;
mutable RecursiveMutex m_luaMutex;
// Paths of all used asset sources, in load order.
diff --git a/source/client/StarClientApplication.cpp b/source/client/StarClientApplication.cpp
index 3c7ec8d..f79226e 100644
--- a/source/client/StarClientApplication.cpp
+++ b/source/client/StarClientApplication.cpp
@@ -73,7 +73,8 @@ Json const AdditionalDefaultConfiguration = Json::parseJson(R"JSON(
"title" : {
"multiPlayerAddress" : "",
"multiPlayerPort" : "",
- "multiPlayerAccount" : ""
+ "multiPlayerAccount" : "",
+ "multiPlayerForceLegacy" : false
},
"bindings" : {
@@ -151,7 +152,7 @@ void ClientApplication::startup(StringList const& cmdLineArgs) {
RootLoader rootLoader({AdditionalAssetsSettings, AdditionalDefaultConfiguration, String("starbound.log"), LogLevel::Info, false, String("starbound.config")});
m_root = rootLoader.initOrDie(cmdLineArgs).first;
- Logger::info("Client Version {} ({}) Source ID: {} Protocol: {}", StarVersionString, StarArchitectureString, StarSourceIdentifierString, StarProtocolVersion);
+ Logger::info("OpenStarbound Client v{} for v{} ({}) Source ID: {} Protocol: {}", OpenStarVersionString, StarVersionString, StarArchitectureString, StarSourceIdentifierString, StarProtocolVersion);
}
void ClientApplication::shutdown() {
@@ -492,6 +493,7 @@ void ClientApplication::renderReload() {
// define post process layers and optionally assign them to groups
m_postProcessLayers.clear();
+ m_labelledPostProcessLayers.clear();
auto postProcessLayers = assets->json("/client.config:postProcessLayers").toArray();
for (auto& layer : postProcessLayers) {
auto effects = jsonToStringList(layer.getArray("effects"));
@@ -502,18 +504,28 @@ void ClientApplication::renderReload() {
if (gname) {
group = &m_postProcessGroups.get(gname.value());
}
+ // I'd think a string map for all of these would be better, but the order does matter here, and does make sense to depend on mod priority, so...
+ // guess a string map of indices works
+ // I tried pointers but for whatever reason the behaviour was highly inconsistent and only worked after reload...
+ auto label = layer.optString("name");
+ if (label) {
+ m_labelledPostProcessLayers.add(label.value(),m_postProcessLayers.count());
+ }
m_postProcessLayers.append(PostProcessLayer{ std::move(effects), (unsigned)layer.getUInt("passes", 1), group });
}
loadEffectConfig("interface");
}
-void ClientApplication::setPostProcessGroupEnabled(String group, bool enabled, Maybe<bool> save) {
+void ClientApplication::setPostProcessLayerPasses(String const& layer, unsigned const& passes) {
+ m_postProcessLayers.at(m_labelledPostProcessLayers.get(layer)).passes = passes;
+}
+void ClientApplication::setPostProcessGroupEnabled(String const& group, bool const& enabled, Maybe<bool> const& save) {
m_postProcessGroups.get(group).enabled = enabled;
if (save && save.value())
m_root->configuration()->setPath(strf("{}.{}.enabled", postProcessGroupsRoot, group),enabled);
}
-bool ClientApplication::postProcessGroupEnabled(String group) {
+bool ClientApplication::postProcessGroupEnabled(String const& group) {
return m_postProcessGroups.get(group).enabled;
}
@@ -627,6 +639,7 @@ void ClientApplication::changeState(MainAppState newState) {
m_titleScreen->setMultiPlayerAddress(toString(address->address()));
m_titleScreen->setMultiPlayerPort(toString(address->port()));
m_titleScreen->setMultiPlayerAccount(configuration->getPath("title.multiPlayerAccount").toString());
+ m_titleScreen->setMultiPlayerForceLegacy(configuration->getPath("title.multiPlayerForceLegacy").optBool().value(false));
m_titleScreen->goToMultiPlayerSelectCharacter(false);
} else {
m_titleScreen->goToMultiPlayerSelectCharacter(true);
@@ -635,6 +648,7 @@ void ClientApplication::changeState(MainAppState newState) {
m_titleScreen->setMultiPlayerAddress(configuration->getPath("title.multiPlayerAddress").toString());
m_titleScreen->setMultiPlayerPort(configuration->getPath("title.multiPlayerPort").toString());
m_titleScreen->setMultiPlayerAccount(configuration->getPath("title.multiPlayerAccount").toString());
+ m_titleScreen->setMultiPlayerForceLegacy(configuration->getPath("title.multiPlayerForceLegacy").optBool().value(false));
}
}
@@ -699,7 +713,7 @@ void ClientApplication::changeState(MainAppState newState) {
bool allowAssetsMismatch = m_root->configuration()->get("allowAssetsMismatch").toBool();
if (auto errorMessage = m_universeClient->connect(UniverseConnection(std::move(packetSocket)), allowAssetsMismatch,
- multiPlayerConnection.account, multiPlayerConnection.password)) {
+ multiPlayerConnection.account, multiPlayerConnection.password, multiPlayerConnection.forceLegacy)) {
setError(*errorMessage);
return;
}
@@ -871,13 +885,15 @@ void ClientApplication::updateTitle(float dt) {
m_pendingMultiPlayerConnection = PendingMultiPlayerConnection{
address.right(),
m_titleScreen->multiPlayerAccount(),
- m_titleScreen->multiPlayerPassword()
+ m_titleScreen->multiPlayerPassword(),
+ m_titleScreen->multiPlayerForceLegacy()
};
auto configuration = m_root->configuration();
configuration->setPath("title.multiPlayerAddress", m_titleScreen->multiPlayerAddress());
configuration->setPath("title.multiPlayerPort", m_titleScreen->multiPlayerPort());
configuration->setPath("title.multiPlayerAccount", m_titleScreen->multiPlayerAccount());
+ configuration->setPath("title.multiPlayerForceLegacy", m_titleScreen->multiPlayerForceLegacy());
changeState(MainAppState::MultiPlayer);
}
diff --git a/source/client/StarClientApplication.hpp b/source/client/StarClientApplication.hpp
index 86b50a3..8824ea0 100644
--- a/source/client/StarClientApplication.hpp
+++ b/source/client/StarClientApplication.hpp
@@ -19,8 +19,9 @@ STAR_CLASS(Voice);
class ClientApplication : public Application {
public:
- void setPostProcessGroupEnabled(String group, bool enabled, Maybe<bool> save);
- bool postProcessGroupEnabled(String group);
+ void setPostProcessLayerPasses(String const& layer, unsigned const& passes);
+ void setPostProcessGroupEnabled(String const& group, bool const& enabled, Maybe<bool> const& save);
+ bool postProcessGroupEnabled(String const& group);
Json postProcessGroups();
protected:
@@ -56,6 +57,7 @@ private:
Variant<P2PNetworkingPeerId, HostAddressWithPort> server;
String account;
String password;
+ bool forceLegacy;
};
struct PostProcessGroup {
@@ -116,6 +118,7 @@ private:
StringMap<PostProcessGroup> m_postProcessGroups;
List<PostProcessLayer> m_postProcessLayers;
+ StringMap<size_t> m_labelledPostProcessLayers;
// Valid if main app state == SinglePlayer
UniverseServerPtr m_universeServer;
diff --git a/source/client/StarRenderingLuaBindings.cpp b/source/client/StarRenderingLuaBindings.cpp
index 39dc1a1..4493f71 100644
--- a/source/client/StarRenderingLuaBindings.cpp
+++ b/source/client/StarRenderingLuaBindings.cpp
@@ -37,6 +37,9 @@ LuaCallbacks LuaBindings::makeRenderingCallbacks(ClientApplication* app) {
auto renderer = app->renderer();
return renderer->getEffectScriptableParameter(effectName, effectParameter);
});
+
+ // not saved; should be loaded by Lua again
+ callbacks.registerCallbackWithSignature<void, String, unsigned>("setPostProcessLayerPasses", bind(mem_fn(&ClientApplication::setPostProcessLayerPasses), app, _1, _2));
return callbacks;
}
diff --git a/source/core/StarDataStream.cpp b/source/core/StarDataStream.cpp
index 7097d63..2688123 100644
--- a/source/core/StarDataStream.cpp
+++ b/source/core/StarDataStream.cpp
@@ -6,7 +6,7 @@
namespace Star {
-unsigned const CurrentStreamVersion = 3;
+unsigned const CurrentStreamVersion = 6; // update OpenProtocolVersion too!
DataStream::DataStream()
: m_byteOrder(ByteOrder::BigEndian),
diff --git a/source/core/StarLua.hpp b/source/core/StarLua.hpp
index 57afb98..fa777c2 100644
--- a/source/core/StarLua.hpp
+++ b/source/core/StarLua.hpp
@@ -1050,6 +1050,9 @@ struct LuaContainerConverter {
template <typename T, typename Allocator>
struct LuaConverter<List<T, Allocator>> : LuaContainerConverter<List<T, Allocator>> {};
+template <typename T, typename Allocator, typename Equals>
+struct LuaConverter<HashSet<T, Allocator, Equals>> : LuaContainerConverter<HashSet<T, Allocator, Equals>> {};
+
template <typename T, size_t MaxSize>
struct LuaConverter<StaticList<T, MaxSize>> : LuaContainerConverter<StaticList<T, MaxSize>> {};
diff --git a/source/core/StarNetCompatibility.cpp b/source/core/StarNetCompatibility.cpp
index cce74dc..220e31e 100644
--- a/source/core/StarNetCompatibility.cpp
+++ b/source/core/StarNetCompatibility.cpp
@@ -2,6 +2,6 @@
namespace Star {
-VersionNumber const OpenProtocolVersion = 4;
+VersionNumber const OpenProtocolVersion = 6; // update StreamCompatibilityVersion too!
} \ No newline at end of file
diff --git a/source/core/StarVersion.cpp.in b/source/core/StarVersion.cpp.in
index 0529c19..bb6ae0b 100644
--- a/source/core/StarVersion.cpp.in
+++ b/source/core/StarVersion.cpp.in
@@ -2,6 +2,7 @@
namespace Star {
+char const* const OpenStarVersionString = "0.1.9";
char const* const StarVersionString = "1.4.4";
char const* const StarSourceIdentifierString = "${STAR_SOURCE_IDENTIFIER}";
char const* const StarArchitectureString = "${STAR_SYSTEM} ${STAR_ARCHITECTURE}";
diff --git a/source/core/StarVersion.hpp b/source/core/StarVersion.hpp
index ad65875..90bc7ea 100644
--- a/source/core/StarVersion.hpp
+++ b/source/core/StarVersion.hpp
@@ -4,6 +4,7 @@
namespace Star {
+extern char const* const OpenStarVersionString;
extern char const* const StarVersionString;
extern char const* const StarSourceIdentifierString;
extern char const* const StarArchitectureString;
diff --git a/source/frontend/StarCharSelection.cpp b/source/frontend/StarCharSelection.cpp
index 2c00b42..c2cc1dc 100644
--- a/source/frontend/StarCharSelection.cpp
+++ b/source/frontend/StarCharSelection.cpp
@@ -15,8 +15,8 @@ CharSelectionPane::CharSelectionPane(PlayerStoragePtr playerStorage,
DeleteCharacterCallback deleteCallback)
: m_playerStorage(playerStorage),
m_downScroll(0),
- m_filteredList({}),
m_search(""),
+ m_filteredList({}),
m_createCallback(createCallback),
m_selectCallback(selectCallback),
m_deleteCallback(deleteCallback) {
diff --git a/source/frontend/StarInterfaceLuaBindings.cpp b/source/frontend/StarInterfaceLuaBindings.cpp
index cbacb59..085cc4c 100644
--- a/source/frontend/StarInterfaceLuaBindings.cpp
+++ b/source/frontend/StarInterfaceLuaBindings.cpp
@@ -55,9 +55,9 @@ LuaCallbacks LuaBindings::makeChatCallbacks(MainInterface* mainInterface, Univer
auto chat = as<Chat>(mainInterface->paneManager()->registeredPane(MainInterfacePanes::Chat).get());
- callbacks.registerCallback("send", [chat, client](String const& message, Maybe<String> modeName, Maybe<bool> speak) {
+ callbacks.registerCallback("send", [chat, client](String const& message, Maybe<String> modeName, Maybe<bool> speak, Maybe<JsonObject> data) {
auto sendMode = modeName ? ChatSendModeNames.getLeft(*modeName) : ChatSendMode::Broadcast;
- client->sendChat(message, sendMode, speak);
+ client->sendChat(message, sendMode, speak, data);
});
// just for SE compat - this shoulda been a utility callback :moyai:
diff --git a/source/frontend/StarTitleScreen.cpp b/source/frontend/StarTitleScreen.cpp
index a32b51a..f1ffcd9 100644
--- a/source/frontend/StarTitleScreen.cpp
+++ b/source/frontend/StarTitleScreen.cpp
@@ -213,6 +213,15 @@ void TitleScreen::setMultiPlayerPassword(String password) {
m_password = std::move(password);
}
+bool TitleScreen::multiPlayerForceLegacy() const {
+ return m_forceLegacy;
+}
+
+void TitleScreen::setMultiPlayerForceLegacy(bool const& forceLegacy) {
+ m_multiPlayerMenu->fetchChild<ButtonWidget>("legacyCheckbox")->setChecked(forceLegacy);
+ m_forceLegacy = forceLegacy;
+}
+
void TitleScreen::initMainMenu() {
m_mainMenu = make_shared<Pane>();
auto backMenu = make_shared<Pane>();
@@ -347,7 +356,8 @@ void TitleScreen::initMultiPlayerMenu() {
{"address", multiPlayerAddress()},
{"account", multiPlayerAccount()},
{"port", multiPlayerPort()},
- //{"password", multiPlayerPassword()}
+ //{"password", multiPlayerPassword()},
+ {"forceLegacy",multiPlayerForceLegacy()}
};
auto serverList = m_serverSelectPane->fetchChild<ListWidget>("serverSelectArea.serverList");
@@ -384,6 +394,7 @@ void TitleScreen::initMultiPlayerMenu() {
setMultiPlayerPort(data.getString("port", ""));
setMultiPlayerAccount(data.getString("account", ""));
setMultiPlayerPassword(data.getString("password", ""));
+ setMultiPlayerForceLegacy(data.getBool("forceLegacy", false));
if (auto passwordWidget = m_multiPlayerMenu->fetchChild("password"))
passwordWidget->focus();
@@ -406,6 +417,10 @@ void TitleScreen::initMultiPlayerMenu() {
readerConnect.registerCallback("password", [=](Widget* obj) {
m_password = convert<TextBoxWidget>(obj)->getText().trim();
});
+
+ readerConnect.registerCallback("legacyCheckbox", [=](Widget* obj) {
+ m_forceLegacy = convert<ButtonWidget>(obj)->isChecked();
+ });
readerConnect.registerCallback("connect", [=](Widget*) {
switchState(TitleState::StartMultiPlayer);
diff --git a/source/frontend/StarTitleScreen.hpp b/source/frontend/StarTitleScreen.hpp
index 3199247..095774f 100644
--- a/source/frontend/StarTitleScreen.hpp
+++ b/source/frontend/StarTitleScreen.hpp
@@ -77,6 +77,9 @@ public:
String multiPlayerPassword() const;
void setMultiPlayerPassword(String password);
+ bool multiPlayerForceLegacy() const;
+ void setMultiPlayerForceLegacy(bool const& forceLegacy);
+
private:
void initMainMenu();
void initCharSelectionMenu();
@@ -122,6 +125,7 @@ private:
String m_connectionPort;
String m_account;
String m_password;
+ bool m_forceLegacy;
CelestialMasterDatabasePtr m_celestialDatabase;
diff --git a/source/game/CMakeLists.txt b/source/game/CMakeLists.txt
index 11e0024..b1a519c 100644
--- a/source/game/CMakeLists.txt
+++ b/source/game/CMakeLists.txt
@@ -250,6 +250,7 @@ SET (star_game_HEADERS
scripting/StarPlayerLuaBindings.hpp
scripting/StarRootLuaBindings.hpp
scripting/StarScriptedAnimatorLuaBindings.hpp
+ scripting/StarSongbookLuaBindings.hpp
scripting/StarStatusControllerLuaBindings.hpp
scripting/StarTeamClientLuaBindings.hpp
scripting/StarWorldLuaBindings.hpp
@@ -491,6 +492,7 @@ SET (star_game_SOURCES
scripting/StarPlayerLuaBindings.cpp
scripting/StarRootLuaBindings.cpp
scripting/StarScriptedAnimatorLuaBindings.cpp
+ scripting/StarSongbookLuaBindings.cpp
scripting/StarStatusControllerLuaBindings.cpp
scripting/StarTeamClientLuaBindings.cpp
scripting/StarWorldLuaBindings.cpp
diff --git a/source/game/StarChatProcessor.cpp b/source/game/StarChatProcessor.cpp
index 2082529..0dd0c48 100644
--- a/source/game/StarChatProcessor.cpp
+++ b/source/game/StarChatProcessor.cpp
@@ -122,7 +122,7 @@ StringList ChatProcessor::activeChannels() const {
return channels;
}
-void ChatProcessor::broadcast(ConnectionId sourceConnectionId, String const& text) {
+void ChatProcessor::broadcast(ConnectionId sourceConnectionId, String const& text, JsonObject data) {
RecursiveMutexLocker locker(m_mutex);
ChatReceivedMessage message = {
@@ -132,6 +132,8 @@ void ChatProcessor::broadcast(ConnectionId sourceConnectionId, String const& tex
text
};
+ message.data = std::move(data);
+
if (handleCommand(message))
return;
@@ -139,7 +141,7 @@ void ChatProcessor::broadcast(ConnectionId sourceConnectionId, String const& tex
pair.second.pendingMessages.append(message);
}
-void ChatProcessor::message(ConnectionId sourceConnectionId, MessageContext::Mode mode, String const& channelName, String const& text) {
+void ChatProcessor::message(ConnectionId sourceConnectionId, MessageContext::Mode mode, String const& channelName, String const& text, JsonObject data) {
RecursiveMutexLocker locker(m_mutex);
ChatReceivedMessage message = {
@@ -149,6 +151,8 @@ void ChatProcessor::message(ConnectionId sourceConnectionId, MessageContext::Mod
text
};
+ message.data = std::move(data);
+
if (handleCommand(message))
return;
@@ -158,11 +162,17 @@ void ChatProcessor::message(ConnectionId sourceConnectionId, MessageContext::Mod
}
}
-void ChatProcessor::whisper(ConnectionId sourceConnectionId, ConnectionId targetClientId, String const& text) {
+void ChatProcessor::whisper(ConnectionId sourceConnectionId, ConnectionId targetClientId, String const& text, JsonObject data) {
RecursiveMutexLocker locker(m_mutex);
ChatReceivedMessage message = {
- {MessageContext::Whisper}, sourceConnectionId, connectionNick(sourceConnectionId), text};
+ {MessageContext::Whisper},
+ sourceConnectionId,
+ connectionNick(sourceConnectionId),
+ text
+ };
+
+ message.data = std::move(data);
if (handleCommand(message))
return;
diff --git a/source/game/StarChatProcessor.hpp b/source/game/StarChatProcessor.hpp
index 89bb5f5..1c42b75 100644
--- a/source/game/StarChatProcessor.hpp
+++ b/source/game/StarChatProcessor.hpp
@@ -41,9 +41,9 @@ public:
StringList clientChannels(ConnectionId clientId) const;
StringList activeChannels() const;
- void broadcast(ConnectionId sourceConnectionId, String const& text);
- void message(ConnectionId sourceConnectionId, MessageContext::Mode context, String const& channelName, String const& text);
- void whisper(ConnectionId sourceConnectionId, ConnectionId targetClientId, String const& text);
+ void broadcast(ConnectionId sourceConnectionId, String const& text, JsonObject data = {});
+ void message(ConnectionId sourceConnectionId, MessageContext::Mode context, String const& channelName, String const& text, JsonObject data = {});
+ void whisper(ConnectionId sourceConnectionId, ConnectionId targetClientId, String const& text, JsonObject data = {});
// Shorthand for passing ServerConnectionId as sourceConnectionId to
// broadcast / message / whisper
diff --git a/source/game/StarChatTypes.cpp b/source/game/StarChatTypes.cpp
index 79dfc4f..56fa6d9 100644
--- a/source/game/StarChatTypes.cpp
+++ b/source/game/StarChatTypes.cpp
@@ -56,6 +56,7 @@ ChatReceivedMessage::ChatReceivedMessage(Json const& json) : ChatReceivedMessage
fromNick = json.getString("fromNick", "");
portrait = json.getString("portrait", "");
text = json.getString("text", "");
+ data = json.getObject("data", JsonObject());
}
Json ChatReceivedMessage::toJson() const {
@@ -67,7 +68,8 @@ Json ChatReceivedMessage::toJson() const {
{"fromConnection", fromConnection},
{"fromNick", fromNick.empty() ? Json() : fromNick},
{"portrait", portrait.empty() ? Json() : portrait},
- {"text", text}
+ {"text", text},
+ {"data", data}
};
}
@@ -78,7 +80,8 @@ DataStream& operator>>(DataStream& ds, ChatReceivedMessage& receivedMessage) {
ds.read(receivedMessage.fromNick);
ds.read(receivedMessage.portrait);
ds.read(receivedMessage.text);
-
+ if (ds.streamCompatibilityVersion() >= 5)
+ ds.read(receivedMessage.data);
return ds;
}
@@ -88,7 +91,8 @@ DataStream& operator<<(DataStream& ds, ChatReceivedMessage const& receivedMessag
ds.write(receivedMessage.fromNick);
ds.write(receivedMessage.portrait);
ds.write(receivedMessage.text);
-
+ if (ds.streamCompatibilityVersion() >= 5)
+ ds.write(receivedMessage.data);
return ds;
}
diff --git a/source/game/StarChatTypes.hpp b/source/game/StarChatTypes.hpp
index 3feb413..3c23d7c 100644
--- a/source/game/StarChatTypes.hpp
+++ b/source/game/StarChatTypes.hpp
@@ -55,6 +55,8 @@ struct ChatReceivedMessage {
String portrait;
String text;
+
+ JsonObject data;
};
DataStream& operator>>(DataStream& ds, ChatReceivedMessage& receivedMessage);
diff --git a/source/game/StarItemBag.cpp b/source/game/StarItemBag.cpp
index 8abdd6f..1f8f74f 100644
--- a/source/game/StarItemBag.cpp
+++ b/source/game/StarItemBag.cpp
@@ -234,17 +234,22 @@ auto ItemBag::itemsFitWhere(ItemConstPtr const& items, uint64_t max) const -> It
return ItemsFitWhereResult();
List<size_t> slots;
+ StableHashSet<size_t> taken;
uint64_t count = std::min(items->count(), max);
while (true) {
if (count == 0)
break;
- size_t slot = bestSlotAvailable(items, false);
+ size_t slot = bestSlotAvailable(items, false, [&](size_t i) {
+ return !taken.contains(i);
+ });
if (slot == NPos)
break;
- else
+ else {
slots.append(slot);
+ taken.insert(slot);
+ }
uint64_t available = stackTransfer(at(slot), items);
if (available != 0)
@@ -350,9 +355,11 @@ uint64_t ItemBag::stackTransfer(ItemConstPtr const& to, ItemConstPtr const& from
return std::min(to->maxStack() - to->count(), from->count());
}
-size_t ItemBag::bestSlotAvailable(ItemConstPtr const& item, bool stacksOnly) const {
+size_t ItemBag::bestSlotAvailable(ItemConstPtr const& item, bool stacksOnly, std::function<bool(size_t)> test) const {
// First look for any slots that can stack, before empty slots.
for (size_t i = 0; i < m_items.size(); ++i) {
+ if (!test(i))
+ continue;
auto const& storedItem = at(i);
if (storedItem && stackTransfer(storedItem, item) != 0)
return i;
@@ -369,4 +376,8 @@ size_t ItemBag::bestSlotAvailable(ItemConstPtr const& item, bool stacksOnly) con
return NPos;
}
+size_t ItemBag::bestSlotAvailable(ItemConstPtr const& item, bool stacksOnly) const {
+ return bestSlotAvailable(item, stacksOnly, [](size_t) { return true; });
+}
+
}
diff --git a/source/game/StarItemBag.hpp b/source/game/StarItemBag.hpp
index 7b0246d..7480d7c 100644
--- a/source/game/StarItemBag.hpp
+++ b/source/game/StarItemBag.hpp
@@ -109,6 +109,7 @@ private:
// Returns the slot that contains the item already and has the *highest*
// stack count but not full, or an empty slot, or NPos for no room.
+ size_t bestSlotAvailable(ItemConstPtr const& item, bool stacksOnly, std::function<bool(size_t)> test) const;
size_t bestSlotAvailable(ItemConstPtr const& item, bool stacksOnly) const;
List<ItemPtr> m_items;
diff --git a/source/game/StarMonster.cpp b/source/game/StarMonster.cpp
index d9ce986..98f4642 100644
--- a/source/game/StarMonster.cpp
+++ b/source/game/StarMonster.cpp
@@ -144,7 +144,7 @@ void Monster::init(World* world, EntityId entityId, EntityMode mode) {
m_scriptComponent.addCallbacks("entity", LuaBindings::makeEntityCallbacks(this));
m_scriptComponent.addCallbacks("animator", LuaBindings::makeNetworkedAnimatorCallbacks(&m_networkedAnimator));
m_scriptComponent.addCallbacks("status", LuaBindings::makeStatusControllerCallbacks(m_statusController.get()));
- m_scriptComponent.addCallbacks("behavior", LuaBindings::makeBehaviorLuaCallbacks(&m_behaviors));
+ m_scriptComponent.addCallbacks("behavior", LuaBindings::makeBehaviorCallbacks(&m_behaviors));
m_scriptComponent.addActorMovementCallbacks(m_movementController.get());
m_scriptComponent.init(world);
}
diff --git a/source/game/StarNetPackets.cpp b/source/game/StarNetPackets.cpp
index 4b16ce8..a121beb 100644
--- a/source/game/StarNetPackets.cpp
+++ b/source/game/StarNetPackets.cpp
@@ -495,14 +495,20 @@ ChatSendPacket::ChatSendPacket() : sendMode(ChatSendMode::Broadcast) {}
ChatSendPacket::ChatSendPacket(String text, ChatSendMode sendMode) : text(std::move(text)), sendMode(sendMode) {}
+ChatSendPacket::ChatSendPacket(String text, ChatSendMode sendMode, JsonObject data) : text(std::move(text)), sendMode(sendMode), data(std::move(data)) {}
+
void ChatSendPacket::read(DataStream& ds) {
ds.read(text);
ds.read(sendMode);
+ if (ds.streamCompatibilityVersion() >= 5)
+ ds.read(data);
}
void ChatSendPacket::write(DataStream& ds) const {
ds.write(text);
ds.write(sendMode);
+ if (ds.streamCompatibilityVersion() >= 5)
+ ds.write(data);
}
CelestialRequestPacket::CelestialRequestPacket() {}
diff --git a/source/game/StarNetPackets.hpp b/source/game/StarNetPackets.hpp
index 8db5c03..63a7ee8 100644
--- a/source/game/StarNetPackets.hpp
+++ b/source/game/StarNetPackets.hpp
@@ -371,12 +371,14 @@ struct FlyShipPacket : PacketBase<PacketType::FlyShip> {
struct ChatSendPacket : PacketBase<PacketType::ChatSend> {
ChatSendPacket();
ChatSendPacket(String text, ChatSendMode sendMode);
+ ChatSendPacket(String text, ChatSendMode sendMode, JsonObject data);
void read(DataStream& ds) override;
void write(DataStream& ds) const override;
String text;
ChatSendMode sendMode;
+ JsonObject data;
};
struct CelestialRequestPacket : PacketBase<PacketType::CelestialRequest> {
diff --git a/source/game/StarNpc.cpp b/source/game/StarNpc.cpp
index 388f6e5..7c1cf63 100644
--- a/source/game/StarNpc.cpp
+++ b/source/game/StarNpc.cpp
@@ -2,6 +2,8 @@
#include "StarDataStreamExtra.hpp"
#include "StarWorld.hpp"
#include "StarRoot.hpp"
+#include "StarSongbook.hpp"
+#include "StarSongbookLuaBindings.hpp"
#include "StarDamageManager.hpp"
#include "StarDamageDatabase.hpp"
#include "StarLogging.hpp"
@@ -76,6 +78,8 @@ Npc::Npc(NpcVariant const& npcVariant)
if (!m_statusController->statusProperty("effectDirectives"))
m_statusController->setStatusProperty("effectDirectives", speciesDefinition->effectDirectives());
+ m_songbook = make_shared<Songbook>(species());
+
m_effectEmitter = make_shared<EffectEmitter>();
m_hitDamageNotificationLimiter = 0;
@@ -185,7 +189,8 @@ void Npc::init(World* world, EntityId entityId, EntityMode mode) {
{ return m_npcVariant.scriptConfig.query(name, def); }));
m_scriptComponent.addCallbacks("entity", LuaBindings::makeEntityCallbacks(this));
m_scriptComponent.addCallbacks("status", LuaBindings::makeStatusControllerCallbacks(m_statusController.get()));
- m_scriptComponent.addCallbacks("behavior", LuaBindings::makeBehaviorLuaCallbacks(&m_behaviors));
+ m_scriptComponent.addCallbacks("behavior", LuaBindings::makeBehaviorCallbacks(&m_behaviors));
+ m_scriptComponent.addCallbacks("songbook", LuaBindings::makeSongbookCallbacks(m_songbook.get()));
m_scriptComponent.addActorMovementCallbacks(m_movementController.get());
m_scriptComponent.init(world);
}
@@ -199,6 +204,8 @@ void Npc::uninit() {
m_scriptComponent.removeCallbacks("config");
m_scriptComponent.removeCallbacks("entity");
m_scriptComponent.removeCallbacks("status");
+ m_scriptComponent.removeCallbacks("behavior");
+ m_scriptComponent.removeCallbacks("songbook");
m_scriptComponent.removeActorMovementCallbacks();
}
m_tools->uninit();
@@ -359,6 +366,8 @@ void Npc::destroy(RenderCallback* renderCallback) {
if (renderCallback && m_deathParticleBurst.get())
renderCallback->addParticles(m_humanoid.particles(*m_deathParticleBurst.get()), position());
+
+ m_songbook->stop();
}
void Npc::damagedOther(DamageNotification const& damage) {
@@ -503,6 +512,7 @@ void Npc::render(RenderCallback* renderCallback) {
renderCallback->addDrawables(m_tools->renderObjectPreviews(aimPosition(), walkingDirection(), inToolRange(), favoriteColor()), renderLayer);
m_effectEmitter->render(renderCallback);
+ m_songbook->render(renderCallback);
}
void Npc::renderLightSources(RenderCallback* renderCallback) {
@@ -571,6 +581,8 @@ void Npc::tickShared(float dt) {
if (m_hitDamageNotificationLimiter)
m_hitDamageNotificationLimiter--;
+ m_songbook->update(*entityMode(), world());
+
m_effectEmitter->setSourcePosition("normal", position());
m_effectEmitter->setSourcePosition("mouth", position() + mouthOffset());
m_effectEmitter->setSourcePosition("feet", position() + feetOffset());
@@ -814,6 +826,8 @@ void Npc::setupNetStates() {
m_netGroup.addNetElement(m_statusController.get());
m_netGroup.addNetElement(m_armor.get());
m_netGroup.addNetElement(m_tools.get());
+ m_songbook->setCompatibilityVersion(6);
+ m_netGroup.addNetElement(m_songbook.get());
m_netGroup.setNeedsStoreCallback(bind(&Npc::setNetStates, this));
m_netGroup.setNeedsLoadCallback(bind(&Npc::getNetStates, this, _1));
@@ -1075,10 +1089,13 @@ bool Npc::consumeEnergy(float energy) {
void Npc::queueUIMessage(String const&) {}
bool Npc::instrumentPlaying() {
- return false; // TODO: remove this from tool user entirely
+ return m_songbook->instrumentPlaying();
}
-void Npc::instrumentEquipped(String const&) {}
+void Npc::instrumentEquipped(String const& instrumentKind) {
+ if (canUseTool())
+ m_songbook->keepAlive(instrumentKind, mouthPosition());
+}
void Npc::interact(InteractAction const&) {}
@@ -1102,6 +1119,10 @@ StatusController* Npc::statusController() {
return m_statusController.get();
}
+Songbook* Npc::songbook() {
+ return m_songbook.get();
+}
+
void Npc::setCameraFocusEntity(Maybe<EntityId> const&) {
// players only
}
diff --git a/source/game/StarNpc.hpp b/source/game/StarNpc.hpp
index 0b22702..21c562c 100644
--- a/source/game/StarNpc.hpp
+++ b/source/game/StarNpc.hpp
@@ -25,6 +25,7 @@
namespace Star {
+STAR_CLASS(Songbook);
STAR_CLASS(Item);
STAR_CLASS(RenderCallback);
STAR_CLASS(Npc);
@@ -165,6 +166,7 @@ public:
void requestEmote(String const& emote) override;
ActorMovementController* movementController() override;
StatusController* statusController() override;
+ Songbook* songbook();
void setCameraFocusEntity(Maybe<EntityId> const& cameraFocusEntity) override;
void playEmote(HumanoidEmote emote) override;
@@ -246,6 +248,7 @@ private:
ArmorWearerPtr m_armor;
ToolUserPtr m_tools;
+ SongbookPtr m_songbook;
NetElementBool m_disableWornArmor;
diff --git a/source/game/StarPlayer.cpp b/source/game/StarPlayer.cpp
index 43add67..facde2e 100644
--- a/source/game/StarPlayer.cpp
+++ b/source/game/StarPlayer.cpp
@@ -3,6 +3,7 @@
#include "StarJsonExtra.hpp"
#include "StarRoot.hpp"
#include "StarSongbook.hpp"
+#include "StarSongbookLuaBindings.hpp"
#include "StarEmoteProcessor.hpp"
#include "StarSpeciesDatabase.hpp"
#include "StarDamageManager.hpp"
@@ -331,6 +332,7 @@ void Player::init(World* world, EntityId entityId, EntityMode mode) {
p.second->addActorMovementCallbacks(m_movementController.get());
p.second->addCallbacks("player", LuaBindings::makePlayerCallbacks(this));
p.second->addCallbacks("status", LuaBindings::makeStatusControllerCallbacks(m_statusController.get()));
+ p.second->addCallbacks("songbook", LuaBindings::makeSongbookCallbacks(m_songbook.get()));
if (m_client)
p.second->addCallbacks("celestial", LuaBindings::makeCelestialCallbacks(m_client));
p.second->init(world);
@@ -362,6 +364,7 @@ void Player::uninit() {
p.second->removeCallbacks("player");
p.second->removeCallbacks("mcontroller");
p.second->removeCallbacks("status");
+ p.second->removeCallbacks("songbook");
p.second->removeCallbacks("world");
if (m_client)
p.second->removeCallbacks("celestial");
@@ -2272,7 +2275,7 @@ bool Player::instrumentPlaying() {
void Player::instrumentEquipped(String const& instrumentKind) {
if (canUseTool())
- m_songbook->keepalive(instrumentKind, mouthPosition());
+ m_songbook->keepAlive(instrumentKind, mouthPosition());
}
void Player::interact(InteractAction const& action) {
diff --git a/source/game/StarPlayerStorage.cpp b/source/game/StarPlayerStorage.cpp
index 7687e97..6be4460 100644
--- a/source/game/StarPlayerStorage.cpp
+++ b/source/game/StarPlayerStorage.cpp
@@ -173,7 +173,7 @@ Json PlayerStorage::savePlayer(PlayerPtr const& player) {
VersionedJson versionedJson = entityFactory->storeVersionedJson(EntityType::Player, playerCacheData);
auto fileName = strf("{}.player", uuidFileName(uuid));
VersionedJson::writeFile(versionedJson, File::relativeTo(m_storageDirectory, fileName));
- Logger::info("Saved player {} to {}", Text::stripEscapeCodes(player->name()), fileName);
+ Logger::debug("Saved player {} to {}", Text::stripEscapeCodes(player->name()), fileName);
}
return newPlayerData;
}
diff --git a/source/game/StarSkyParameters.cpp b/source/game/StarSkyParameters.cpp
index e2ed885..3d540b8 100644
--- a/source/game/StarSkyParameters.cpp
+++ b/source/game/StarSkyParameters.cpp
@@ -175,6 +175,8 @@ void SkyParameters::read(DataStream& ds) {
ds >> sunType;
if (ds.streamCompatibilityVersion() >= 3)
ds >> settings;
+ else
+ settings = JsonObject();
}
void SkyParameters::write(DataStream& ds) const {
diff --git a/source/game/StarSongbook.cpp b/source/game/StarSongbook.cpp
index 68db655..72f2b2b 100644
--- a/source/game/StarSongbook.cpp
+++ b/source/game/StarSongbook.cpp
@@ -158,7 +158,7 @@ void Songbook::render(RenderCallback* renderCallback) {
m_pendingAudio.clear();
}
-void Songbook::keepalive(String const& instrument, Vec2F const& position) {
+void Songbook::keepAlive(String const& instrument, Vec2F const& position) {
if (instrument != m_instrument) {
m_instrument = instrument;
m_dataUpdated = true;
@@ -681,11 +681,11 @@ void Songbook::play(Json const& song, String const& timeSource) {
m_activeCooldown = 3;
}
-bool Songbook::active() {
+bool Songbook::active() const {
return m_activeCooldown > 0;
}
-bool Songbook::instrumentPlaying() {
+bool Songbook::instrumentPlaying() const {
if (!active())
return false;
if (m_timeSourceInstance) {
@@ -698,6 +698,18 @@ bool Songbook::instrumentPlaying() {
return false;
}
+Maybe<String> Songbook::timeSource() const {
+ return m_timeSource;
+}
+
+Maybe<String> Songbook::instrument() const {
+ return m_instrument;
+}
+
+Json Songbook::song() const {
+ return m_song;
+}
+
double Songbook::fundamentalFrequency(double p) {
return 55.0 * pow(2.0, (p - 69.0) / 12.0 + 3.0);
}
diff --git a/source/game/StarSongbook.hpp b/source/game/StarSongbook.hpp
index 89a4bfd..6f15242 100644
--- a/source/game/StarSongbook.hpp
+++ b/source/game/StarSongbook.hpp
@@ -24,12 +24,16 @@ public:
// instrument needs to tell the songbook what type it is, and needs to keep
// calling it to signal
// the instrument is still equiped
- void keepalive(String const& instrument, Vec2F const& position);
+ void keepAlive(String const& instrument, Vec2F const& position);
void stop();
- void play(Json const& song, String const& timesource);
- bool active();
- bool instrumentPlaying();
+ void play(Json const& song, String const& timeSource);
+ bool active() const;
+ bool instrumentPlaying() const;
+
+ Maybe<String> timeSource() const;
+ Maybe<String> instrument() const;
+ Json song() const;
private:
struct Note {
diff --git a/source/game/StarStagehand.cpp b/source/game/StarStagehand.cpp
index d85f77b..1207d91 100644
--- a/source/game/StarStagehand.cpp
+++ b/source/game/StarStagehand.cpp
@@ -43,7 +43,7 @@ void Stagehand::init(World* world, EntityId entityId, EntityMode mode) {
return m_config.query(name, def);
}));
m_scriptComponent.addCallbacks("entity", LuaBindings::makeEntityCallbacks(this));
- m_scriptComponent.addCallbacks("behavior", LuaBindings::makeBehaviorLuaCallbacks(&m_behaviors));
+ m_scriptComponent.addCallbacks("behavior", LuaBindings::makeBehaviorCallbacks(&m_behaviors));
m_scriptComponent.init(world);
}
}
diff --git a/source/game/StarUniverseClient.cpp b/source/game/StarUniverseClient.cpp
index af33508..b41d19e 100644
--- a/source/game/StarUniverseClient.cpp
+++ b/source/game/StarUniverseClient.cpp
@@ -71,7 +71,7 @@ PlayerPtr UniverseClient::mainPlayer() const {
return m_mainPlayer;
}
-Maybe<String> UniverseClient::connect(UniverseConnection connection, bool allowAssetsMismatch, String const& account, String const& password) {
+Maybe<String> UniverseClient::connect(UniverseConnection connection, bool allowAssetsMismatch, String const& account, String const& password, bool const& forceLegacy) {
auto& root = Root::singleton();
auto assets = root.assets();
@@ -85,9 +85,11 @@ Maybe<String> UniverseClient::connect(UniverseConnection connection, bool allowA
{
auto protocolRequest = make_shared<ProtocolRequestPacket>(StarProtocolVersion);
- protocolRequest->setCompressionMode(PacketCompressionMode::Enabled);
- // Signal that we're OpenStarbound. Vanilla Starbound only compresses
- // packets above 64 bytes - by forcing it, we can communicate this.
+ if (!forceLegacy) {
+ protocolRequest->setCompressionMode(PacketCompressionMode::Enabled);
+ // Signal that we're OpenStarbound. Vanilla Starbound only compresses
+ // packets above 64 bytes - by forcing it, we can communicate this.
+ }
connection.pushSingle(protocolRequest);
}
connection.sendAll(timeout);
@@ -101,7 +103,7 @@ Maybe<String> UniverseClient::connect(UniverseConnection connection, bool allowA
NetCompatibilityRules compatibilityRules;
compatibilityRules.setVersion(LegacyVersion);
- bool legacyServer = protocolResponsePacket->compressionMode() != PacketCompressionMode::Enabled;
+ bool legacyServer = forceLegacy || (protocolResponsePacket->compressionMode() != PacketCompressionMode::Enabled);
if (!legacyServer) {
auto compressedSocket = as<CompressedPacketSocket>(&connection.packetSocket());
if (protocolResponsePacket->info) {
@@ -484,10 +486,13 @@ bool UniverseClient::flying() const {
return false;
}
-void UniverseClient::sendChat(String const& text, ChatSendMode sendMode, Maybe<bool> speak) {
+void UniverseClient::sendChat(String const& text, ChatSendMode sendMode, Maybe<bool> speak, Maybe<JsonObject> data) {
if (speak.value(!text.beginsWith("/")))
m_mainPlayer->addChatMessage(text);
- m_connection->pushSingle(make_shared<ChatSendPacket>(text, sendMode));
+ auto packet = make_shared<ChatSendPacket>(text, sendMode);
+ if (data)
+ packet->data = std::move(*data);
+ m_connection->pushSingle(packet);
}
List<ChatReceivedMessage> UniverseClient::pullChatMessages() {
diff --git a/source/game/StarUniverseClient.hpp b/source/game/StarUniverseClient.hpp
index b770b07..b1c589f 100644
--- a/source/game/StarUniverseClient.hpp
+++ b/source/game/StarUniverseClient.hpp
@@ -41,7 +41,7 @@ public:
PlayerPtr mainPlayer() const;
// Returns error if connection failed
- Maybe<String> connect(UniverseConnection connection, bool allowAssetsMismatch, String const& account = "", String const& password = "");
+ Maybe<String> connect(UniverseConnection connection, bool allowAssetsMismatch, String const& account = "", String const& password = "", bool const& forceLegacy = false);
bool isConnected() const;
void disconnect();
Maybe<String> disconnectReason() const;
@@ -80,7 +80,7 @@ public:
SkyConstPtr currentSky() const;
bool flying() const;
- void sendChat(String const& text, ChatSendMode sendMode, Maybe<bool> speak = {});
+ void sendChat(String const& text, ChatSendMode sendMode, Maybe<bool> speak = {}, Maybe<JsonObject> data = {});
List<ChatReceivedMessage> pullChatMessages();
uint16_t players();
diff --git a/source/game/StarUniverseServer.cpp b/source/game/StarUniverseServer.cpp
index f32f650..977dc71 100644
--- a/source/game/StarUniverseServer.cpp
+++ b/source/game/StarUniverseServer.cpp
@@ -1064,16 +1064,19 @@ void UniverseServer::processChat() {
for (auto const& p : take(m_pendingChat)) {
if (auto clientContext = m_clients.get(p.first)) {
for (auto const& chat : p.second) {
+ auto& message = get<0>(chat);
+ auto sendMode = get<1>(chat);
+ auto& data = get<2>(chat);
if (clientContext->remoteAddress())
- Logger::info("Chat: <{}> {}", clientContext->playerName(), chat.first);
+ Logger::info("Chat: <{}> {}", clientContext->playerName(), message);
auto team = m_teamManager->getTeam(clientContext->playerUuid());
- if (chat.second == ChatSendMode::Broadcast)
- m_chatProcessor->broadcast(p.first, chat.first);
- else if (chat.second == ChatSendMode::Party && team.isValid())
- m_chatProcessor->message(p.first, MessageContext::Mode::Party, team.value().hex(), chat.first);
+ if (sendMode == ChatSendMode::Broadcast)
+ m_chatProcessor->broadcast(p.first, message, std::move(data));
+ else if (sendMode == ChatSendMode::Party && team.isValid())
+ m_chatProcessor->message(p.first, MessageContext::Mode::Party, team.value().hex(), message, std::move(data));
else
- m_chatProcessor->message(p.first, MessageContext::Mode::Local, printWorldId(clientContext->playerWorldId()), chat.first);
+ m_chatProcessor->message(p.first, MessageContext::Mode::Local, printWorldId(clientContext->playerWorldId()), message, std::move(data));
}
}
}
@@ -1527,7 +1530,7 @@ void UniverseServer::packetsReceived(UniverseConnectionServer*, ConnectionId cli
} else if (auto chatSend = as<ChatSendPacket>(packet)) {
RecursiveMutexLocker locker(m_mainLock);
- m_pendingChat[clientId].append({std::move(chatSend->text), chatSend->sendMode});
+ m_pendingChat[clientId].append(make_tuple(std::move(chatSend->text), chatSend->sendMode, std::move(chatSend->data)));
} else if (auto clientContextUpdatePacket = as<ClientContextUpdatePacket>(packet)) {
clientContext->readUpdate(std::move(clientContextUpdatePacket->updateData));
diff --git a/source/game/StarUniverseServer.hpp b/source/game/StarUniverseServer.hpp
index f3db6fc..ddf7d0c 100644
--- a/source/game/StarUniverseServer.hpp
+++ b/source/game/StarUniverseServer.hpp
@@ -254,7 +254,7 @@ private:
HashMap<ConnectionId, String> m_pendingDisconnections;
HashMap<ConnectionId, List<WorkerPoolPromise<CelestialResponse>>> m_pendingCelestialRequests;
List<pair<WorldId, UniverseFlagAction>> m_pendingFlagActions;
- HashMap<ConnectionId, List<pair<String, ChatSendMode>>> m_pendingChat;
+ HashMap<ConnectionId, List<tuple<String, ChatSendMode, JsonObject>>> m_pendingChat;
Maybe<WorkerPoolPromise<CelestialCoordinate>> m_nextRandomizedStarterWorld;
Map<WorldId, List<WorldServerThread::Message>> m_pendingWorldMessages;
diff --git a/source/game/scripting/StarBehaviorLuaBindings.cpp b/source/game/scripting/StarBehaviorLuaBindings.cpp
index 8866746..4bf16f2 100644
--- a/source/game/scripting/StarBehaviorLuaBindings.cpp
+++ b/source/game/scripting/StarBehaviorLuaBindings.cpp
@@ -4,7 +4,7 @@
namespace Star {
-LuaCallbacks LuaBindings::makeBehaviorLuaCallbacks(List<BehaviorStatePtr>* list) {
+LuaCallbacks LuaBindings::makeBehaviorCallbacks(List<BehaviorStatePtr>* list) {
LuaCallbacks callbacks;
callbacks.registerCallback("behavior", [list](Json const& config, JsonObject const& parameters, LuaTable context, Maybe<LuaUserData> blackboard) -> BehaviorStateWeakPtr {
diff --git a/source/game/scripting/StarBehaviorLuaBindings.hpp b/source/game/scripting/StarBehaviorLuaBindings.hpp
index d2a882b..01c04ab 100644
--- a/source/game/scripting/StarBehaviorLuaBindings.hpp
+++ b/source/game/scripting/StarBehaviorLuaBindings.hpp
@@ -9,6 +9,6 @@ STAR_CLASS(Root);
STAR_CLASS(UniverseClient);
namespace LuaBindings {
- LuaCallbacks makeBehaviorLuaCallbacks(List<BehaviorStatePtr>* list);
+ LuaCallbacks makeBehaviorCallbacks(List<BehaviorStatePtr>* list);
}
}
diff --git a/source/game/scripting/StarPlayerLuaBindings.cpp b/source/game/scripting/StarPlayerLuaBindings.cpp
index 5af86d0..ea2bae5 100644..100755
--- a/source/game/scripting/StarPlayerLuaBindings.cpp
+++ b/source/game/scripting/StarPlayerLuaBindings.cpp
@@ -496,6 +496,10 @@ LuaCallbacks LuaBindings::makePlayerCallbacks(Player* player) {
return QuestStateNames.getRight(player->questManager()->getQuest(questId)->state());
});
+ callbacks.registerCallback("questObjectives", [player](String const& questId) -> Maybe<JsonArray> {
+ return player->questManager()->getQuest(questId)->objectiveList();
+ });
+
callbacks.registerCallback("callQuest", [player](String const& questId, String const& func, LuaVariadic<LuaValue> const& args) -> Maybe<LuaValue> {
if (!player->questManager()->hasQuest(questId))
return {};
@@ -522,8 +526,11 @@ LuaCallbacks LuaBindings::makePlayerCallbacks(Player* player) {
return player->questManager()->trackedQuestId();
});
- callbacks.registerCallback("setTrackedQuest", [player](Maybe<String> const& questId) {
- return player->questManager()->setAsTracked(questId);
+ callbacks.registerCallback("setTrackedQuest", [player](String const& questId) {
+ if (!player->questManager()->isCurrent(questId))
+ return player->questManager()->setAsTracked(questId);
+ else
+ return player->questManager()->setAsTracked({});
});
callbacks.registerCallback("canTurnInQuest", [player](String const& questId) {
diff --git a/source/game/scripting/StarRootLuaBindings.cpp b/source/game/scripting/StarRootLuaBindings.cpp
index c45ef46..4e60595 100644
--- a/source/game/scripting/StarRootLuaBindings.cpp
+++ b/source/game/scripting/StarRootLuaBindings.cpp
@@ -66,13 +66,12 @@ LuaCallbacks LuaBindings::makeRootCallbacks() {
callbacks.registerCallbackWithSignature<Maybe<String>, String, Maybe<String>>("materialMiningSound", bind(RootCallbacks::materialMiningSound, root, _1, _2));
callbacks.registerCallbackWithSignature<Maybe<String>, String, Maybe<String>>("materialFootstepSound", bind(RootCallbacks::materialFootstepSound, root, _1, _2));
- callbacks.registerCallback("assetsByExtension", [root](LuaEngine& engine, String const& extension) -> LuaTable {
- auto& extensions = root->assets()->scanExtension(extension);
- auto table = engine.createTable(extensions.size(), 0);
- size_t i = 0;
- for (auto& file : extensions)
- table.set(++i, file);
- return table;
+ callbacks.registerCallback("assetsByExtension", [root](String const& extension) -> CaseInsensitiveStringSet {
+ return root->assets()->scanExtension(extension);
+ });
+
+ callbacks.registerCallback("assetsScan", [root]( Maybe<String> const& a, Maybe<String> const& b) -> StringList {
+ return b ? root->assets()->scan(a.value(), *b) : root->assets()->scan(a.value());
});
callbacks.registerCallback("assetOrigin", [root](String const& path) -> Maybe<String> {
@@ -116,12 +115,12 @@ LuaCallbacks LuaBindings::makeRootCallbacks() {
return table;
});
- callbacks.registerCallback("assetSourceMetadata", [root](LuaEngine& engine, String const& assetSourcePath) {
+ callbacks.registerCallback("assetSourceMetadata", [root](String const& assetSourcePath) {
auto assets = root->assets();
return assets->assetSourceMetadata(assetSourcePath);
});
- callbacks.registerCallback("itemFile", [root](LuaEngine& engine, String const& itemName) -> Maybe<String> {
+ callbacks.registerCallback("itemFile", [root](String const& itemName) -> Maybe<String> {
return root->itemDatabase()->itemFile(itemName);
});
diff --git a/source/game/scripting/StarScriptableThread.cpp b/source/game/scripting/StarScriptableThread.cpp
index cbd32ad..6bbfece 100644
--- a/source/game/scripting/StarScriptableThread.cpp
+++ b/source/game/scripting/StarScriptableThread.cpp
@@ -14,9 +14,9 @@ namespace Star {
ScriptableThread::ScriptableThread(Json parameters)
: Thread("ScriptableThread: " + parameters.getString("name")), // TODO
m_stop(false),
+ m_parameters(std::move(parameters)),
m_errorOccurred(false),
- m_shouldExpire(true),
- m_parameters(std::move(parameters)) {
+ m_shouldExpire(true) {
m_luaRoot = make_shared<LuaRoot>();
m_name = m_parameters.getString("name");
@@ -78,8 +78,6 @@ void ScriptableThread::passMessage(Message&& message) {
void ScriptableThread::run() {
try {
- auto& root = Root::singleton();
-
double updateMeasureWindow = m_parameters.getDouble("updateMeasureWindow",0.5);
TickRateApproacher tickApproacher(1.0f / m_timestep, updateMeasureWindow);
diff --git a/source/game/scripting/StarSongbookLuaBindings.cpp b/source/game/scripting/StarSongbookLuaBindings.cpp
new file mode 100644
index 0000000..7831ed6
--- /dev/null
+++ b/source/game/scripting/StarSongbookLuaBindings.cpp
@@ -0,0 +1,21 @@
+#include "StarSongbookLuaBindings.hpp"
+#include "StarLuaConverters.hpp"
+
+namespace Star {
+
+LuaCallbacks LuaBindings::makeSongbookCallbacks(Songbook* songbook) {
+ LuaCallbacks callbacks;
+
+ callbacks.registerCallbackWithSignature<void, Json, String>("play", bind(mem_fn(&Songbook::play), songbook, _1, _2));
+ callbacks.registerCallbackWithSignature<void, String, Vec2F>("keepAlive", bind(mem_fn(&Songbook::keepAlive), songbook, _1, _2));
+ callbacks.registerCallbackWithSignature<void>("stop", bind(mem_fn(&Songbook::stop), songbook));
+ callbacks.registerCallbackWithSignature<bool>("active", bind(mem_fn(&Songbook::active), songbook));
+ callbacks.registerCallbackWithSignature<Maybe<String>>("band", bind(mem_fn(&Songbook::timeSource), songbook));
+ callbacks.registerCallbackWithSignature<Maybe<String>>("instrument", bind(mem_fn(&Songbook::instrument), songbook));
+ callbacks.registerCallbackWithSignature<bool>("instrumentPlaying", bind(mem_fn(&Songbook::instrumentPlaying), songbook));
+ callbacks.registerCallbackWithSignature<Json>("song", bind(mem_fn(&Songbook::song), songbook));
+
+ return callbacks;
+}
+
+}
diff --git a/source/game/scripting/StarSongbookLuaBindings.hpp b/source/game/scripting/StarSongbookLuaBindings.hpp
new file mode 100644
index 0000000..cc55ec6
--- /dev/null
+++ b/source/game/scripting/StarSongbookLuaBindings.hpp
@@ -0,0 +1,11 @@
+#pragma once
+
+#include "StarLua.hpp"
+#include "StarSongbook.hpp"
+
+namespace Star {
+
+namespace LuaBindings {
+ LuaCallbacks makeSongbookCallbacks(Songbook* songbook);
+}
+}
diff --git a/source/server/main.cpp b/source/server/main.cpp
index de09efa..ac40524 100644
--- a/source/server/main.cpp
+++ b/source/server/main.cpp
@@ -45,7 +45,7 @@ int main(int argc, char** argv) {
auto configuration = root->configuration();
{
- Logger::info("Server Version {} ({}) Source ID: {} Protocol: {}", StarVersionString, StarArchitectureString, StarSourceIdentifierString, StarProtocolVersion);
+ Logger::info("OpenStarbound Server v{} for v{} ({}) Source ID: {} Protocol: {}", OpenStarVersionString, StarVersionString, StarArchitectureString, StarSourceIdentifierString, StarProtocolVersion);
float updateRate = 1.0f / GlobalTimestep;
if (auto jUpdateRate = configuration->get("updateRate")) {