[world] added scripting feature settings: show/hid scripting related stuff, see #71
Dieser Commit ist enthalten in:
Ursprung
de717fef67
Commit
9a387bdaac
@ -1,9 +1,8 @@
|
||||
/**
|
||||
* client/src/mainwindow.cpp
|
||||
* This file is part of Traintastic,
|
||||
* see <https://github.com/traintastic/traintastic>.
|
||||
*
|
||||
* This file is part of the traintastic source code.
|
||||
*
|
||||
* Copyright (C) 2019-2025 Reinder Feenstra
|
||||
* Copyright (C) 2019-2026 Reinder Feenstra
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -765,6 +764,19 @@ void MainWindow::worldChanged()
|
||||
|
||||
m_worldSimulationAction->setEnabled(simulation->getAttributeBool(AttributeName::Enabled, true));
|
||||
}
|
||||
|
||||
if(auto* property = m_world->getProperty("lua_scripts")) [[likely]]
|
||||
{
|
||||
connect(property, &AbstractProperty::attributeChanged,
|
||||
[this](AttributeName name, const QVariant& value)
|
||||
{
|
||||
if(name == AttributeName::Visible)
|
||||
{
|
||||
m_actionLuaScript->setVisible(value.toBool());
|
||||
}
|
||||
});
|
||||
m_actionLuaScript->setVisible(property->getAttributeBool(AttributeName::Visible, true));
|
||||
}
|
||||
}
|
||||
|
||||
static_cast<MainWindowStatusBar*>(statusBar())->worldChanged();
|
||||
@ -1079,8 +1091,6 @@ void MainWindow::updateActions()
|
||||
worldStateChanged(haveWorld ? m_connection->world()->getProperty("state")->toInt64() : 0);
|
||||
|
||||
setMenuEnabled(m_menuObjects, haveWorld);
|
||||
if(haveWorld && !m_connection->world()->hasProperty("lua_scripts"))
|
||||
m_actionLuaScript->setEnabled(false);
|
||||
|
||||
if(connected && !haveWorld)
|
||||
{
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
/**
|
||||
* server/src/core/idobject.cpp
|
||||
* This file is part of Traintastic,
|
||||
* see <https://github.com/traintastic/traintastic>.
|
||||
*
|
||||
* Copyright (C) 2019-2023 Reinder Feenstra
|
||||
* Copyright (C) 2019-2026 Reinder Feenstra
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -46,6 +47,7 @@ IdObject::IdObject(World& world, std::string_view _id) :
|
||||
|
||||
Attributes::addDisplayName(id, DisplayName::Object::id);
|
||||
Attributes::addEnabled(id, editable);
|
||||
Attributes::addVisible(id, m_world.feature(WorldFeature::Scripting));
|
||||
m_interfaceItems.add(id);
|
||||
}
|
||||
|
||||
@ -57,6 +59,12 @@ void IdObject::destroying()
|
||||
Object::destroying();
|
||||
}
|
||||
|
||||
void IdObject::loaded()
|
||||
{
|
||||
Object::loaded();
|
||||
Attributes::setVisible(id, m_world.feature(WorldFeature::Scripting));
|
||||
}
|
||||
|
||||
void IdObject::addToWorld()
|
||||
{
|
||||
m_world.m_objects.emplace(id, weak_from_this());
|
||||
@ -68,3 +76,10 @@ void IdObject::worldEvent(WorldState state, WorldEvent event)
|
||||
|
||||
Attributes::setEnabled(id, contains(state, WorldState::Edit));
|
||||
}
|
||||
|
||||
void IdObject::worldFeaturesChanged(const WorldFeatures features, WorldFeature changed)
|
||||
{
|
||||
Object::worldFeaturesChanged(features, changed);
|
||||
|
||||
Attributes::setVisible(id, features[WorldFeature::Scripting]);
|
||||
}
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
/**
|
||||
* server/src/core/idobject.hpp
|
||||
* This file is part of Traintastic,
|
||||
* see <https://github.com/traintastic/traintastic>.
|
||||
*
|
||||
* This file is part of the traintastic source code.
|
||||
*
|
||||
* Copyright (C) 2019-2020,2023 Reinder Feenstra
|
||||
* Copyright (C) 2019-2026 Reinder Feenstra
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -60,8 +59,10 @@ class IdObject : public Object
|
||||
|
||||
IdObject(World& world, std::string_view _id);
|
||||
void destroying() override;
|
||||
void loaded() override;
|
||||
virtual void addToWorld();
|
||||
void worldEvent(WorldState state, WorldEvent event) override;
|
||||
void worldFeaturesChanged(const WorldFeatures features, WorldFeature changed) override;
|
||||
|
||||
public:
|
||||
Property<std::string> id;
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
/**
|
||||
* server/src/core/object.cpp
|
||||
* This file is part of Traintastic,
|
||||
* see <https://github.com/traintastic/traintastic>.
|
||||
*
|
||||
* This file is part of the traintastic source code.
|
||||
*
|
||||
* Copyright (C) 2019-2021,2023-2024 Reinder Feenstra
|
||||
* Copyright (C) 2019-2026 Reinder Feenstra
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -28,6 +27,7 @@
|
||||
#include "abstractproperty.hpp"
|
||||
#include "abstractobjectproperty.hpp"
|
||||
#include "abstractvectorproperty.hpp"
|
||||
#include "../world/worldfeatures.hpp"
|
||||
#include "../world/worldloader.hpp"
|
||||
#include "../world/worldsaver.hpp"
|
||||
|
||||
@ -165,14 +165,49 @@ void Object::worldEvent(WorldState state, WorldEvent event)
|
||||
if(AbstractProperty* property = dynamic_cast<AbstractProperty*>(&it.second);
|
||||
property && contains(property->flags(), PropertyFlags::SubObject))
|
||||
{
|
||||
property->toObject()->worldEvent(state, event);
|
||||
if(auto object = property->toObject())
|
||||
{
|
||||
object->worldEvent(state, event);
|
||||
}
|
||||
}
|
||||
else if(AbstractVectorProperty* vectorProperty = dynamic_cast<AbstractVectorProperty*>(&it.second);
|
||||
vectorProperty && contains(vectorProperty->flags(), PropertyFlags::SubObject))
|
||||
{
|
||||
const size_t size = vectorProperty->size();
|
||||
for(size_t i = 0; i < size; i++)
|
||||
vectorProperty->getObject(i)->worldEvent(state, event);
|
||||
{
|
||||
if(auto object = vectorProperty->getObject(i)) [[likely]]
|
||||
{
|
||||
object->worldEvent(state, event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Object::worldFeaturesChanged(WorldFeatures features, WorldFeature changed)
|
||||
{
|
||||
for(const auto& it : m_interfaceItems)
|
||||
{
|
||||
if(AbstractProperty* property = dynamic_cast<AbstractProperty*>(&it.second);
|
||||
property && contains(property->flags(), PropertyFlags::SubObject))
|
||||
{
|
||||
if(auto object = property->toObject())
|
||||
{
|
||||
object->worldFeaturesChanged(features, changed);
|
||||
}
|
||||
}
|
||||
else if(AbstractVectorProperty* vectorProperty = dynamic_cast<AbstractVectorProperty*>(&it.second);
|
||||
vectorProperty && contains(vectorProperty->flags(), PropertyFlags::SubObject))
|
||||
{
|
||||
const size_t size = vectorProperty->size();
|
||||
for(size_t i = 0; i < size; i++)
|
||||
{
|
||||
if(auto object = vectorProperty->getObject(i)) [[likely]]
|
||||
{
|
||||
object->worldFeaturesChanged(features, changed);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
/**
|
||||
* server/src/core/object.hpp
|
||||
* This file is part of Traintastic,
|
||||
* see <https://github.com/traintastic/traintastic>.
|
||||
*
|
||||
* This file is part of the traintastic source code.
|
||||
*
|
||||
* Copyright (C) 2019-2024 Reinder Feenstra
|
||||
* Copyright (C) 2019-2026 Reinder Feenstra
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -44,6 +43,8 @@ class AbstractObjectProperty;
|
||||
class AbstractVectorProperty;
|
||||
class AbstractAttribute;
|
||||
class AbstractEvent;
|
||||
enum class WorldFeature;
|
||||
class WorldFeatures;
|
||||
class WorldLoader;
|
||||
class WorldSaver;
|
||||
|
||||
@ -91,6 +92,7 @@ class Object : public std::enable_shared_from_this<Object>
|
||||
virtual void save(WorldSaver& saver, nlohmann::json& data, nlohmann::json& state) const;
|
||||
virtual void loaded();
|
||||
virtual void worldEvent(WorldState state, WorldEvent event);
|
||||
virtual void worldFeaturesChanged(WorldFeatures features, WorldFeature changed);
|
||||
|
||||
public:
|
||||
Object(const Object&) = delete;
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
/**
|
||||
* server/src/lua/script.cpp
|
||||
* This file is part of Traintastic,
|
||||
* see <https://github.com/traintastic/traintastic>.
|
||||
*
|
||||
* This file is part of the traintastic source code.
|
||||
*
|
||||
* Copyright (C) 2019-2025 Reinder Feenstra
|
||||
* Copyright (C) 2019-2026 Reinder Feenstra
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -155,12 +154,19 @@ void Script::loaded()
|
||||
break;
|
||||
|
||||
case LuaScriptState::Running:
|
||||
startSandbox();
|
||||
if(state == LuaScriptState::Running)
|
||||
if(m_world.feature(WorldFeature::Scripting))
|
||||
{
|
||||
updateEnabled(); // setState doesn't updateEnabled() because the state is already running
|
||||
auto& running = m_world.luaScripts->status->running;
|
||||
running.setValueInternal(running + 1); // setState doesn't increment because the state is already running
|
||||
startSandbox();
|
||||
if(state == LuaScriptState::Running)
|
||||
{
|
||||
updateEnabled(); // setState doesn't updateEnabled() because the state is already running
|
||||
auto& running = m_world.luaScripts->status->running;
|
||||
running.setValueInternal(running + 1); // setState doesn't increment because the state is already running
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
state.setValueInternal(LuaScriptState::Stopped);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -176,6 +182,18 @@ void Script::worldEvent(WorldState worldState, WorldEvent worldEvent)
|
||||
updateEnabled();
|
||||
}
|
||||
|
||||
void Script::worldFeaturesChanged(const WorldFeatures features, WorldFeature changed)
|
||||
{
|
||||
IdObject::worldFeaturesChanged(features, changed);
|
||||
|
||||
if(!features[WorldFeature::Scripting] && m_sandbox)
|
||||
{
|
||||
stopSandbox();
|
||||
}
|
||||
|
||||
updateEnabled();
|
||||
}
|
||||
|
||||
void Script::updateEnabled()
|
||||
{
|
||||
const bool editable = contains(m_world.state.value(), WorldState::Edit) && state != LuaScriptState::Running;
|
||||
@ -186,7 +204,7 @@ void Script::updateEnabled()
|
||||
Attributes::setEnabled(disabled, editable);
|
||||
Attributes::setEnabled(code, editable);
|
||||
|
||||
Attributes::setEnabled(start, stoppedOrError);
|
||||
Attributes::setEnabled(start, stoppedOrError && m_world.feature(WorldFeature::Scripting));
|
||||
Attributes::setEnabled(stop, state == LuaScriptState::Running);
|
||||
Attributes::setEnabled(clearPersistentVariables, stoppedOrError && !m_persistentVariables.empty());
|
||||
|
||||
@ -231,6 +249,12 @@ void Script::setState(LuaScriptState value)
|
||||
void Script::startSandbox()
|
||||
{
|
||||
assert(!m_sandbox);
|
||||
|
||||
if(!m_world.feature(WorldFeature::Scripting))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if((m_sandbox = Sandbox::create(*this)))
|
||||
{
|
||||
Log::log(*this, LogMessage::N9001_STARTING_SCRIPT);
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
/**
|
||||
* server/src/lua/script.hpp
|
||||
* This file is part of Traintastic,
|
||||
* see <https://github.com/traintastic/traintastic>.
|
||||
*
|
||||
* This file is part of the traintastic source code.
|
||||
*
|
||||
* Copyright (C) 2019-2025 Reinder Feenstra
|
||||
* Copyright (C) 2019-2026 Reinder Feenstra
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -47,6 +46,7 @@ class Script : public IdObject
|
||||
void destroying() final;
|
||||
void loaded() final;
|
||||
void worldEvent(WorldState worldState, WorldEvent worldEvent) final;
|
||||
void worldFeaturesChanged(const WorldFeatures features, WorldFeature changed) final;
|
||||
|
||||
void updateEnabled();
|
||||
void setState(LuaScriptState value);
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
/**
|
||||
* server/src/lua/scriptlist.cpp
|
||||
* This file is part of Traintastic,
|
||||
* see <https://github.com/traintastic/traintastic>.
|
||||
*
|
||||
* This file is part of the traintastic source code.
|
||||
*
|
||||
* Copyright (C) 2019-2024 Reinder Feenstra
|
||||
* Copyright (C) 2019-2026 Reinder Feenstra
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -93,7 +92,7 @@ ScriptList::ScriptList(Object& _parent, std::string_view parentPropertyName)
|
||||
|
||||
ScriptList::~ScriptList()
|
||||
{
|
||||
getWorld(parent()).statuses.removeInternal(status.value());
|
||||
removeStatus();
|
||||
}
|
||||
|
||||
TableModelPtr ScriptList::getModel()
|
||||
@ -101,6 +100,16 @@ TableModelPtr ScriptList::getModel()
|
||||
return std::make_shared<ScriptListTableModel>(*this);
|
||||
}
|
||||
|
||||
void ScriptList::loaded()
|
||||
{
|
||||
ObjectList<Script>::loaded();
|
||||
|
||||
if(!getWorld(parent()).feature(WorldFeature::Scripting))
|
||||
{
|
||||
removeStatus();
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptList::worldEvent(WorldState state, WorldEvent event)
|
||||
{
|
||||
ObjectList<Script>::worldEvent(state, event);
|
||||
@ -111,11 +120,28 @@ void ScriptList::worldEvent(WorldState state, WorldEvent event)
|
||||
Attributes::setEnabled(delete_, editable);
|
||||
}
|
||||
|
||||
void ScriptList::worldFeaturesChanged(const WorldFeatures features, WorldFeature changed)
|
||||
{
|
||||
ObjectList<Script>::worldFeaturesChanged(features, changed);
|
||||
|
||||
if(changed == WorldFeature::Scripting && !empty())
|
||||
{
|
||||
if(features[WorldFeature::Scripting])
|
||||
{
|
||||
addStatus();
|
||||
}
|
||||
else if(!features[WorldFeature::Scripting])
|
||||
{
|
||||
removeStatus();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptList::objectAdded(const std::shared_ptr<Script>& /*object*/)
|
||||
{
|
||||
if(m_items.size() == 1)
|
||||
{
|
||||
getWorld(parent()).statuses.appendInternal(status.value());
|
||||
addStatus();
|
||||
}
|
||||
updateEnabled();
|
||||
}
|
||||
@ -124,7 +150,7 @@ void ScriptList::objectRemoved(const std::shared_ptr<Script>& /*object*/)
|
||||
{
|
||||
if(empty())
|
||||
{
|
||||
getWorld(parent()).statuses.removeInternal(status.value());
|
||||
removeStatus();
|
||||
}
|
||||
updateEnabled();
|
||||
}
|
||||
@ -152,4 +178,14 @@ void ScriptList::updateEnabled()
|
||||
Attributes::setEnabled(clearPersistentVariables, canClearPersistentVariables);
|
||||
}
|
||||
|
||||
void ScriptList::addStatus()
|
||||
{
|
||||
getWorld(parent()).statuses.appendInternal(status.value());
|
||||
}
|
||||
|
||||
void ScriptList::removeStatus()
|
||||
{
|
||||
getWorld(parent()).statuses.removeInternal(status.value());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
/**
|
||||
* server/src/lua/scriptlist.hpp
|
||||
* This file is part of Traintastic,
|
||||
* see <https://github.com/traintastic/traintastic>.
|
||||
*
|
||||
* This file is part of the traintastic source code.
|
||||
*
|
||||
* Copyright (C) 2019-2024 Reinder Feenstra
|
||||
* Copyright (C) 2019-2026 Reinder Feenstra
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -34,7 +33,9 @@ namespace Lua {
|
||||
class ScriptList final : public ObjectList<Script>
|
||||
{
|
||||
protected:
|
||||
void loaded() final;
|
||||
void worldEvent(WorldState state, WorldEvent event) final;
|
||||
void worldFeaturesChanged(const WorldFeatures features, WorldFeature changed) final;
|
||||
void objectAdded(const std::shared_ptr<Script>& /*object*/) final;
|
||||
void objectRemoved(const std::shared_ptr<Script>& /*object*/) final;
|
||||
bool isListedProperty(std::string_view name) final;
|
||||
@ -55,6 +56,10 @@ class ScriptList final : public ObjectList<Script>
|
||||
TableModelPtr getModel() final;
|
||||
|
||||
void updateEnabled();
|
||||
|
||||
private:
|
||||
void addStatus();
|
||||
void removeStatus();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
/**
|
||||
* server/src/utils/category.hpp
|
||||
* This file is part of Traintastic,
|
||||
* see <https://github.com/traintastic/traintastic>.
|
||||
*
|
||||
* This file is part of the traintastic source code.
|
||||
*
|
||||
* Copyright (C) 2021-2025 Reinder Feenstra
|
||||
* Copyright (C) 2021-2026 Reinder Feenstra
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -34,6 +33,7 @@ namespace Category
|
||||
constexpr std::string_view debug = "category:debug";
|
||||
constexpr std::string_view developer = "category:developer";
|
||||
constexpr std::string_view driver = "category:driver";
|
||||
constexpr std::string_view features = "category:features";
|
||||
constexpr std::string_view general = "category:general";
|
||||
constexpr std::string_view info = "category:info";
|
||||
constexpr std::string_view input = "category:input";
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
/**
|
||||
* server/src/world/world.cpp
|
||||
* This file is part of Traintastic,
|
||||
* see <https://github.com/traintastic/traintastic>.
|
||||
*
|
||||
* This file is part of the traintastic source code.
|
||||
*
|
||||
* Copyright (C) 2019-2025 Reinder Feenstra
|
||||
* Copyright (C) 2019-2026 Reinder Feenstra
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -173,6 +172,11 @@ World::World(Private /*unused*/) :
|
||||
correctOutputPosWhenLocked{this, "correct_output_pos_when_locked", true, PropertyFlags::ReadWrite | PropertyFlags::Store | PropertyFlags::NoScript},
|
||||
extOutputChangeAction{this, "ext_output_change_action", ExternalOutputChangeAction::EmergencyStopTrain, PropertyFlags::ReadWrite | PropertyFlags::Store | PropertyFlags::NoScript},
|
||||
pathReleaseDelay{this, "path_release_delay", 5000, PropertyFlags::ReadWrite | PropertyFlags::Store | PropertyFlags::NoScript},
|
||||
featureScripting{this, "feature_scripting", true, PropertyFlags::ReadWrite | PropertyFlags::Store,
|
||||
[this](bool value)
|
||||
{
|
||||
setFeature(WorldFeature::Scripting, value);
|
||||
}},
|
||||
debugBlockEvents{this, "debug_block_events", false, PropertyFlags::ReadWrite | PropertyFlags::Store | PropertyFlags::NoScript},
|
||||
debugTrainEvents{this, "debug_train_events", false, PropertyFlags::ReadWrite | PropertyFlags::Store | PropertyFlags::NoScript},
|
||||
debugZoneEvents{this, "debug_zone_events", false, PropertyFlags::ReadWrite | PropertyFlags::Store | PropertyFlags::NoScript},
|
||||
@ -369,6 +373,10 @@ World::World(Private /*unused*/) :
|
||||
Attributes::addMinMax(pathReleaseDelay, {0, 15000}); // Up to 15 seconds
|
||||
m_interfaceItems.add(pathReleaseDelay);
|
||||
|
||||
// Features:
|
||||
Attributes::addCategory(featureScripting, Category::features);
|
||||
m_interfaceItems.add(featureScripting);
|
||||
|
||||
// Debug options:
|
||||
Attributes::addCategory(debugBlockEvents, Category::debug);
|
||||
m_interfaceItems.add(debugBlockEvents);
|
||||
@ -417,6 +425,7 @@ World::World(Private /*unused*/) :
|
||||
Attributes::addObjectEditor(railVehicles, false);
|
||||
m_interfaceItems.add(railVehicles);
|
||||
Attributes::addObjectEditor(luaScripts, false);
|
||||
Attributes::addVisible(luaScripts, featureScripting);
|
||||
m_interfaceItems.add(luaScripts);
|
||||
|
||||
Attributes::addObjectEditor(blockRailTiles, false);
|
||||
@ -470,6 +479,7 @@ World::World(Private /*unused*/) :
|
||||
m_interfaceItems.add(onEvent);
|
||||
|
||||
updateEnabled();
|
||||
updateFeatures();
|
||||
}
|
||||
|
||||
World::~World()
|
||||
@ -565,6 +575,7 @@ void World::export_(std::vector<std::byte>& data)
|
||||
|
||||
void World::loaded()
|
||||
{
|
||||
updateFeatures();
|
||||
updateScaleRatio();
|
||||
Object::loaded();
|
||||
}
|
||||
@ -582,6 +593,13 @@ void World::worldEvent(WorldState worldState, WorldEvent worldEvent)
|
||||
fireEvent(onEvent, worldState, worldEvent);
|
||||
}
|
||||
|
||||
void World::worldFeaturesChanged(const WorldFeatures features, WorldFeature changed)
|
||||
{
|
||||
Object::worldFeaturesChanged(features, changed);
|
||||
|
||||
Attributes::setVisible(luaScripts, features[WorldFeature::Scripting]);
|
||||
}
|
||||
|
||||
void World::event(const WorldEvent value)
|
||||
{
|
||||
// Update state:
|
||||
@ -664,6 +682,20 @@ void World::event(const WorldEvent value)
|
||||
it.second.lock()->worldEvent(worldState, value);
|
||||
}
|
||||
|
||||
void World::setFeature(WorldFeature feature, bool value)
|
||||
{
|
||||
if(m_features[feature] != value)
|
||||
{
|
||||
m_features.set(feature, value);
|
||||
|
||||
worldFeaturesChanged(m_features, feature);
|
||||
for(auto& it : m_objects)
|
||||
{
|
||||
it.second.lock()->worldFeaturesChanged(m_features, feature);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void World::updateEnabled()
|
||||
{
|
||||
const bool isOnline = contains(state.value(), WorldState::Online);
|
||||
@ -673,6 +705,12 @@ void World::updateEnabled()
|
||||
Attributes::setEnabled(simulation, !isOnline && !isPoweredOn && !isRunning);
|
||||
}
|
||||
|
||||
void World::updateFeatures()
|
||||
{
|
||||
m_features.set(WorldFeature::Scripting, featureScripting);
|
||||
Attributes::setVisible(luaScripts, feature(WorldFeature::Scripting));
|
||||
}
|
||||
|
||||
void World::updateScaleRatio()
|
||||
{
|
||||
if(scale != WorldScale::Custom)
|
||||
|
||||
@ -1,9 +1,8 @@
|
||||
/**
|
||||
* server/src/world/world.hpp
|
||||
* This file is part of Traintastic,
|
||||
* see <https://github.com/traintastic/traintastic>.
|
||||
*
|
||||
* This file is part of the traintastic source code.
|
||||
*
|
||||
* Copyright (C) 2019-2025 Reinder Feenstra
|
||||
* Copyright (C) 2019-2026 Reinder Feenstra
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
@ -23,6 +22,7 @@
|
||||
#ifndef TRAINTASTIC_SERVER_WORLD_WORLD_HPP
|
||||
#define TRAINTASTIC_SERVER_WORLD_WORLD_HPP
|
||||
|
||||
#include "worldfeatures.hpp"
|
||||
#include "../core/object.hpp"
|
||||
#include "../core/property.hpp"
|
||||
#include "../core/objectproperty.hpp"
|
||||
@ -80,7 +80,10 @@ class World : public Object
|
||||
private:
|
||||
struct Private {};
|
||||
|
||||
WorldFeatures m_features;
|
||||
|
||||
void updateEnabled();
|
||||
void updateFeatures();
|
||||
void updateScaleRatio();
|
||||
|
||||
protected:
|
||||
@ -90,7 +93,10 @@ class World : public Object
|
||||
|
||||
void loaded() final;
|
||||
void worldEvent(WorldState worldState, WorldEvent worldEvent) final;
|
||||
void worldFeaturesChanged(const WorldFeatures features, WorldFeature changed) final;
|
||||
|
||||
void event(WorldEvent value);
|
||||
void setFeature(WorldFeature feature, bool value);
|
||||
|
||||
public:
|
||||
CLASS_ID("world")
|
||||
@ -114,6 +120,8 @@ class World : public Object
|
||||
Property<ExternalOutputChangeAction> extOutputChangeAction;
|
||||
Property<uint16_t> pathReleaseDelay;
|
||||
|
||||
Property<bool> featureScripting;
|
||||
|
||||
Property<bool> debugBlockEvents;
|
||||
Property<bool> debugTrainEvents;
|
||||
Property<bool> debugZoneEvents;
|
||||
@ -170,6 +178,16 @@ class World : public Object
|
||||
World(Private);
|
||||
~World() override;
|
||||
|
||||
inline bool feature(WorldFeature feature) const
|
||||
{
|
||||
return m_features[feature];
|
||||
}
|
||||
|
||||
const WorldFeatures features() const
|
||||
{
|
||||
return m_features;
|
||||
}
|
||||
|
||||
std::string getObjectId() const final { return std::string(classId); }
|
||||
|
||||
std::string getUniqueId(std::string_view prefix) const;
|
||||
|
||||
84
server/src/world/worldfeatures.hpp
Normale Datei
84
server/src/world/worldfeatures.hpp
Normale Datei
@ -0,0 +1,84 @@
|
||||
/**
|
||||
* This file is part of Traintastic,
|
||||
* see <https://github.com/traintastic/traintastic>.
|
||||
*
|
||||
* Copyright (C) 2026 Reinder Feenstra
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef TRAINTASTIC_SERVER_WORLD_WORLDFEATURES_HPP
|
||||
#define TRAINTASTIC_SERVER_WORLD_WORLDFEATURES_HPP
|
||||
|
||||
#include <cstdint>
|
||||
#include <array>
|
||||
|
||||
enum class WorldFeature
|
||||
{
|
||||
Scripting = 0,
|
||||
};
|
||||
|
||||
class WorldFeatures
|
||||
{
|
||||
public:
|
||||
constexpr WorldFeatures() noexcept
|
||||
: m_features{0}
|
||||
{
|
||||
}
|
||||
|
||||
constexpr WorldFeatures(std::initializer_list<WorldFeature> features) noexcept
|
||||
: WorldFeatures()
|
||||
{
|
||||
for(auto f : features)
|
||||
{
|
||||
set(f, true);
|
||||
}
|
||||
}
|
||||
|
||||
constexpr bool operator [](WorldFeature f) const noexcept
|
||||
{
|
||||
return (m_features[index(f)] & bit(f)) != 0;
|
||||
}
|
||||
|
||||
constexpr void set(WorldFeature f, bool enable) noexcept
|
||||
{
|
||||
if(enable)
|
||||
{
|
||||
m_features[index(f)] |= bit(f);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_features[index(f)] &= ~bit(f);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
using ET = uint8_t;
|
||||
using UT = std::underlying_type_t<WorldFeature>;
|
||||
|
||||
std::array<ET, 1> m_features;
|
||||
|
||||
static constexpr std::size_t index(WorldFeature f) noexcept
|
||||
{
|
||||
return static_cast<UT>(f) / (sizeof(ET) * 8);
|
||||
}
|
||||
|
||||
static constexpr ET bit(WorldFeature f) noexcept
|
||||
{
|
||||
return static_cast<ET>(1) << (static_cast<UT>(f) % (sizeof(ET) * 8));
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -251,6 +251,10 @@
|
||||
"term": "category:developer",
|
||||
"definition": "Developer"
|
||||
},
|
||||
{
|
||||
"term": "category:features",
|
||||
"definition": "Features"
|
||||
},
|
||||
{
|
||||
"term": "category:general",
|
||||
"definition": "General"
|
||||
@ -3215,6 +3219,10 @@
|
||||
"term": "world:ext_output_change_action",
|
||||
"definition": "External output change action"
|
||||
},
|
||||
{
|
||||
"term": "world:feature_scripting",
|
||||
"definition": "Scripting"
|
||||
},
|
||||
{
|
||||
"term": "world:inputs",
|
||||
"definition": "Inputs"
|
||||
|
||||
Laden…
x
In neuem Issue referenzieren
Einen Benutzer sperren