diff options
author | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-06-20 14:33:09 +1000 |
---|---|---|
committer | Kae <80987908+Novaenia@users.noreply.github.com> | 2023-06-20 14:33:09 +1000 |
commit | 6352e8e3196f78388b6c771073f9e03eaa612673 (patch) | |
tree | e23772f79a7fbc41bc9108951e9e136857484bf4 /source/game/StarTechController.cpp | |
parent | 6741a057e5639280d85d0f88ba26f000baa58f61 (diff) |
everything everywhere
all at once
Diffstat (limited to 'source/game/StarTechController.cpp')
-rw-r--r-- | source/game/StarTechController.cpp | 536 |
1 files changed, 536 insertions, 0 deletions
diff --git a/source/game/StarTechController.cpp b/source/game/StarTechController.cpp new file mode 100644 index 0000000..1734c61 --- /dev/null +++ b/source/game/StarTechController.cpp @@ -0,0 +1,536 @@ +#include "StarTechController.hpp" +#include "StarStatusController.hpp" +#include "StarDataStreamExtra.hpp" +#include "StarJsonExtra.hpp" +#include "StarLuaGameConverters.hpp" +#include "StarWorldLuaBindings.hpp" +#include "StarConfigLuaBindings.hpp" +#include "StarEntityLuaBindings.hpp" +#include "StarNetworkedAnimatorLuaBindings.hpp" +#include "StarStatusControllerLuaBindings.hpp" +#include "StarRoot.hpp" +#include "StarScriptedEntity.hpp" +#include "StarLoungingEntities.hpp" +#include "StarWorld.hpp" +#include "StarLogging.hpp" + +namespace Star { + +EnumMap<TechController::ParentState> const TechController::ParentStateNames{ + {TechController::ParentState::Stand, "Stand"}, + {TechController::ParentState::Fly, "Fly"}, + {TechController::ParentState::Fall, "Fall"}, + {TechController::ParentState::Sit, "Sit"}, + {TechController::ParentState::Lay, "Lay"}, + {TechController::ParentState::Duck, "Duck"}, + {TechController::ParentState::Walk, "Walk"}, + {TechController::ParentState::Run, "Run"}, + {TechController::ParentState::Swim, "Swim"} +}; + +TechController::TechController() { + m_parentEntity = nullptr; + m_movementController = nullptr; + m_statusController = nullptr; + + m_moveRun = false; + m_movePrimaryFire = false; + m_moveAltFire = false; + m_moveUp = false; + m_moveDown = false; + m_moveLeft = false; + m_moveRight = false; + m_moveJump = false; + m_moveSpecial1 = false; + m_moveSpecial2 = false; + m_moveSpecial3 = false; + + addNetElement(&m_techAnimators); + addNetElement(&m_parentState); + addNetElement(&m_parentDirectives); + addNetElement(&m_xParentOffset); + addNetElement(&m_yParentOffset); + addNetElement(&m_parentHidden); + addNetElement(&m_toolUsageSuppressed); + + m_xParentOffset.setFixedPointBase(0.003125); + m_yParentOffset.setFixedPointBase(0.003125); +} + +Json TechController::diskStore() { + if (m_overriddenTech) { + auto modules = JsonArray(); + for (String moduleName : *m_overriddenTech) + modules.append(JsonObject{{"module", moduleName}, {"scriptData", JsonObject()}}); + return JsonObject{{"techModules", modules}}; + } else { + return JsonObject{{"techModules", transform<JsonArray>(m_techModules, [](TechModule const& tm) { + return JsonObject{ + {"module", tm.config.name}, + {"scriptData", tm.scriptComponent.getScriptStorage()} + }; + }) + }}; + } +} + +void TechController::diskLoad(Json const& store) { + setupTechModules( store.getArray("techModules", {}).transformed([](Json const& v) { + return make_tuple(v.getString("module"), v.getObject("scriptData", {})); + })); +} + +void TechController::init(Entity* parentEntity, ActorMovementController* movementController, StatusController* statusController) { + m_parentEntity = parentEntity; + m_movementController = movementController; + m_statusController = statusController; + + m_moveRun = false; + m_movePrimaryFire = false; + m_moveAltFire = false; + resetMoves(); + + if (m_parentEntity->isMaster()) + initializeModules(); +} + +void TechController::uninit() { + m_parentEntity = nullptr; + m_movementController = nullptr; + m_statusController = nullptr; + + for (auto& module : m_techModules) + unloadModule(module); +} + +void TechController::setLoadedTech(StringList const& techModules, bool forceLoad) { + if (forceLoad || loadedTech() != techModules) { + setupTechModules(techModules.transformed([](String const& module) { return make_tuple(module, JsonObject()); })); + if (m_parentEntity) + initializeModules(); + } +} + +StringList TechController::loadedTech() const { + return transform<StringList>(m_techModules, [](TechModule const& tm) { return tm.config.name; }); +} + +void TechController::reloadTech() { + setLoadedTech(loadedTech(), true); +} + +bool TechController::techOverridden() const { + return (bool)m_overriddenTech; +} + +void TechController::setOverrideTech(StringList const& techModules) { + if (!m_overriddenTech) + m_overriddenTech = loadedTech(); + + setLoadedTech(techModules, true); +} + +void TechController::clearOverrideTech() { + if (m_overriddenTech) { + setLoadedTech(*m_overriddenTech, true); + m_overriddenTech = {}; + } +} + +void TechController::setShouldRun(bool shouldRun) { + m_moveRun = shouldRun; +} + +void TechController::beginPrimaryFire() { + m_movePrimaryFire = true; +} + +void TechController::beginAltFire() { + m_moveAltFire = true; +} + +void TechController::endPrimaryFire() { + m_movePrimaryFire = false; +} + +void TechController::endAltFire() { + m_moveAltFire = false; +} + +void TechController::moveUp() { + m_moveUp = true; +} + +void TechController::moveDown() { + m_moveDown = true; +} + +void TechController::moveLeft() { + m_moveLeft = true; +} + +void TechController::moveRight() { + m_moveRight = true; +} + +void TechController::jump() { + m_moveJump = true; +} + +void TechController::special(int specialKey) { + if (specialKey == 1) + m_moveSpecial1 = true; + if (specialKey == 2) + m_moveSpecial2 = true; + if (specialKey == 3) + m_moveSpecial3 = true; +} + +void TechController::setAimPosition(Vec2F const& aimPosition) { + m_aimPosition = aimPosition; +} + +void TechController::tickMaster() { + // if there's no gravity, fly instead of walking + if (m_movementController->zeroG()) { + if (m_moveRight || m_moveLeft || m_moveUp || m_moveDown) { + Vec2F flightControl = {0, 0}; + + if (m_moveRight) + flightControl[0]++; + if (m_moveLeft) + flightControl[0]--; + if (m_moveUp) + flightControl[1]++; + if (m_moveDown) + flightControl[1]--; + + m_movementController->controlFly(flightControl); + } + } else { + if (m_moveLeft != m_moveRight) + m_movementController->controlMove(m_moveLeft ? Direction::Left : Direction::Right, m_moveRun); + + if (m_moveJump && !m_moveDown) + m_movementController->controlJump(); + + if (m_movementController->onGround() && m_moveDown && !m_moveJump) + m_movementController->controlCrouch(); + else if (m_moveDown) + m_movementController->controlDown(); + } + + for (auto& module : m_techModules) { + JsonObject moves = { + {"run", m_moveRun}, + {"up", m_moveUp}, + {"down", m_moveDown}, + {"left", m_moveLeft}, + {"right", m_moveRight}, + {"jump", m_moveJump}, + {"primaryFire", m_movePrimaryFire}, + {"altFire", m_moveAltFire}, + {"special1", m_moveSpecial1}, + {"special2", m_moveSpecial2}, + {"special3", m_moveSpecial3} + }; + + module.scriptComponent.update(JsonObject{{"moves", moves}, {"dt", WorldTimestep}}); + } + + resetMoves(); + updateAnimators(); +} + +void TechController::tickSlave() { + resetMoves(); + updateAnimators(); +} + +Maybe<TechController::ParentState> TechController::parentState() const { + return m_parentState.get(); +} + +String TechController::parentDirectives() const { + return m_parentDirectives.get(); +} + +Vec2F TechController::parentOffset() const { + return {m_xParentOffset.get(), m_yParentOffset.get()}; +} + +bool TechController::toolUsageSuppressed() const { + return m_toolUsageSuppressed.get(); +} + +bool TechController::parentHidden() const { + return m_parentHidden.get(); +} + +List<Drawable> TechController::backDrawables() { + List<Drawable> drawables; + + for (auto const& animator : m_techAnimators.netElements()) { + if (animator->isVisible()) { + for (auto& piece : animator->animator.drawablesWithZLevel(m_movementController->position())) { + if (piece.second < 0.0f) + drawables.append(move(piece.first)); + } + } + } + + return drawables; +} + +List<Drawable> TechController::frontDrawables() { + List<Drawable> drawables; + + for (auto const& animator : m_techAnimators.netElements()) { + if (animator->isVisible()) { + for (auto& piece : animator->animator.drawablesWithZLevel(m_movementController->position())) { + if (piece.second >= 0.0f) + drawables.append(move(piece.first)); + } + } + } + + return drawables; +} + +List<LightSource> TechController::lightSources() const { + List<LightSource> lightSources; + + for (auto const& animator : m_techAnimators.netElements()) { + if (animator->isVisible()) + lightSources.appendAll(animator->animator.lightSources(m_movementController->position())); + } + + return lightSources; +} + +List<AudioInstancePtr> TechController::pullNewAudios() { + List<AudioInstancePtr> newAudios; + + for (auto const& animator : m_techAnimators.netElements()) { + if (animator->isVisible()) + newAudios.appendAll(animator->dynamicTarget.pullNewAudios()); + else + animator->dynamicTarget.pullNewAudios(); + } + + return newAudios; +} + +List<Particle> TechController::pullNewParticles() { + List<Particle> newParticles; + + for (auto const& animator : m_techAnimators.netElements()) { + if (animator->isVisible()) + newParticles.appendAll(animator->dynamicTarget.pullNewParticles()); + else + animator->dynamicTarget.pullNewParticles(); + } + + return newParticles; +} + +Maybe<Json> TechController::receiveMessage(String const& message, bool localMessage, JsonArray const& args) { + for (auto& module : m_techModules) { + if (auto res = module.scriptComponent.handleMessage(message, localMessage, args)) + return res; + } + return {}; +} + +TechController::TechAnimator::TechAnimator(Maybe<String> ac) { + animationConfig = move(ac); + animator = animationConfig ? NetworkedAnimator(*animationConfig) : NetworkedAnimator(); + netGroup.addNetElement(&animator); + netGroup.addNetElement(&visible); +} + +void TechController::TechAnimator::initNetVersion(NetElementVersion const* version) { + netGroup.initNetVersion(version); +} + +void TechController::TechAnimator::netStore(DataStream& ds) const { + ds << animationConfig; + netGroup.netStore(ds); +} + +void TechController::TechAnimator::netLoad(DataStream& ds) { + ds >> animationConfig; + animator = animationConfig ? NetworkedAnimator(*animationConfig) : NetworkedAnimator(); + netGroup.netLoad(ds); +} + +void TechController::TechAnimator::enableNetInterpolation(float extrapolationHint) { + netGroup.enableNetInterpolation(extrapolationHint); +} + +void TechController::TechAnimator::disableNetInterpolation() { + netGroup.disableNetInterpolation(); +} + +void TechController::TechAnimator::tickNetInterpolation(float dt) { + netGroup.tickNetInterpolation(dt); +} + +bool TechController::TechAnimator::writeNetDelta(DataStream& ds, uint64_t fromVersion) const { + return netGroup.writeNetDelta(ds, fromVersion); +} + +void TechController::TechAnimator::readNetDelta(DataStream& ds, float interpolationTime) { + netGroup.readNetDelta(ds, interpolationTime); +} + +void TechController::TechAnimator::blankNetDelta(float interpolationTime) { + netGroup.blankNetDelta(interpolationTime); +} + +void TechController::TechAnimator::setVisible(bool visible) { + this->visible.set(visible); + if (!visible) + dynamicTarget.stopAudio(); +} + +bool TechController::TechAnimator::isVisible() const { + return visible.get(); +} + +void TechController::setupTechModules(List<tuple<String, JsonObject>> const& moduleInits) { + for (auto& techModule : m_techModules) + unloadModule(techModule); + + m_techModules.clear(); + m_techAnimators.clearNetElements(); + + auto techDatabase = Root::singleton().techDatabase(); + + for (auto const& moduleInit : moduleInits) { + if (techDatabase->contains(get<0>(moduleInit))) { + auto& module = m_techModules.emplaceAppend(); + + module.config = techDatabase->tech(get<0>(moduleInit)); + + module.scriptComponent.setScripts(module.config.scripts); + module.scriptComponent.setScriptStorage(get<1>(moduleInit)); + + module.visible = module.config.parameters.getBool("visible", true); + + module.toolUsageSuppressed = false; + + auto moduleAnimator = make_shared<TechAnimator>(module.config.animationConfig); + for (auto const& pair : module.config.parameters.get("animationParts", JsonObject()).iterateObject()) + moduleAnimator->animator.setPartTag(pair.first, "partImage", pair.second.toString()); + module.animatorId = m_techAnimators.addNetElement(moduleAnimator); + } else { + Logger::warn("Tech module '%s' not found in tech database", get<0>(moduleInit)); + } + } +} + +void TechController::unloadModule(TechModule& techModule) { + techModule.scriptComponent.uninit(); + techModule.scriptComponent.removeCallbacks("tech"); + techModule.scriptComponent.removeCallbacks("config"); + techModule.scriptComponent.removeCallbacks("entity"); + techModule.scriptComponent.removeCallbacks("animator"); + techModule.scriptComponent.removeCallbacks("status"); + techModule.scriptComponent.removeActorMovementCallbacks(); +} + +void TechController::initializeModules() { + for (auto& module : m_techModules) { + module.scriptComponent.addCallbacks("tech", makeTechCallbacks(module)); + module.scriptComponent.addCallbacks("config", LuaBindings::makeConfigCallbacks([&module](String const& name, Json const& def) { + return module.config.parameters.query(name, def); + })); + module.scriptComponent.addCallbacks("entity", LuaBindings::makeEntityCallbacks(m_parentEntity)); + module.scriptComponent.addCallbacks("animator", LuaBindings::makeNetworkedAnimatorCallbacks(&m_techAnimators.getNetElement(module.animatorId)->animator)); + module.scriptComponent.addCallbacks("status", LuaBindings::makeStatusControllerCallbacks(m_statusController)); + module.scriptComponent.addActorMovementCallbacks(m_movementController); + + module.scriptComponent.init(m_parentEntity->world()); + } +} + +void TechController::resetMoves() { + m_moveRun = false; + m_moveUp = false; + m_moveDown = false; + m_moveLeft = false; + m_moveRight = false; + m_moveJump = false; + m_moveSpecial1 = false; + m_moveSpecial2 = false; + m_moveSpecial3 = false; +} + +void TechController::updateAnimators() { + for (auto const& module : m_techModules) + m_techAnimators.getNetElement(module.animatorId)->setVisible(module.visible); + + for (auto const& animator : m_techAnimators.netElements()) { + if (m_parentEntity->world()->isServer() || !animator->isVisible()) { + animator->animator.update(WorldTimestep, nullptr); + } else { + animator->animator.update(WorldTimestep, &animator->dynamicTarget); + animator->dynamicTarget.updatePosition(m_movementController->position()); + } + } +} + +LuaCallbacks TechController::makeTechCallbacks(TechModule& techModule) { + LuaCallbacks callbacks; + + callbacks.registerCallback("aimPosition", [this]() { + return m_aimPosition; + }); + + callbacks.registerCallback("setVisible", [&techModule](bool visible) { + techModule.visible = visible; + }); + + callbacks.registerCallback("setParentState", [this](Maybe<String> const& state) { + if (state) + m_parentState.set(ParentStateNames.getLeft(*state)); + else + m_parentState.set({}); + }); + + callbacks.registerCallback("setParentDirectives", [this, &techModule](Maybe<String> const& directives) { + techModule.parentDirectives = directives.value(); + String newParentDirectives; + for (auto& module : m_techModules) + newParentDirectives += module.parentDirectives; + m_parentDirectives.set(newParentDirectives); + }); + + callbacks.registerCallback("setParentHidden", [this](bool hidden) { + m_parentHidden.set(hidden); + }); + + callbacks.registerCallback("setParentOffset", [this](Vec2F const& po) { + m_xParentOffset.set(po[0]); + m_yParentOffset.set(po[1]); + }); + + callbacks.registerCallback("parentLounging", [this]() { + if (auto loungingEntity = as<LoungingEntity>(m_parentEntity)) + return loungingEntity->loungingIn().isValid(); + return false; + }); + + callbacks.registerCallback("setToolUsageSuppressed", [this, &techModule](bool suppressed) { + techModule.toolUsageSuppressed = suppressed; + bool anySuppressed = false; + for (auto& module : m_techModules) + anySuppressed = anySuppressed || module.toolUsageSuppressed; + m_toolUsageSuppressed.set(anySuppressed); + }); + + return callbacks; +} + +} |