Making host_activity.cc public

This commit is contained in:
Eric Froemling 2021-10-25 14:23:20 -05:00
parent 733c47352c
commit ecc5a359c1
No known key found for this signature in database
GPG Key ID: 89C93F0F8D6D5A98
4 changed files with 573 additions and 42 deletions

View File

@ -3965,50 +3965,50 @@
"assets/src/ba_data/python/ba/_generated/__init__.py": "https://files.ballistica.net/cache/ba1/ee/e8/cad05aa531c7faf7ff7b96db7f6e",
"assets/src/ba_data/python/ba/_generated/enums.py": "https://files.ballistica.net/cache/ba1/72/82/86956fae909ac2fe2a1abd84a361",
"ballisticacore-windows/Generic/BallisticaCore.ico": "https://files.ballistica.net/cache/ba1/89/c0/e32c7d2a35dc9aef57cc73b0911a",
"build/prefab/full/linux_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/ad/1b/13d2e47149d4804419bbc2d97145",
"build/prefab/full/linux_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/70/fb/15b9f7cf5ab14c4555471639ddeb",
"build/prefab/full/linux_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/74/1d/fc9e33e565475daaac80da5252f0",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/40/83/5514e4fc477d23dd035e4dbf441a",
"build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/4b/de/c54388a6e7c64c917c8b4a7c2ba5",
"build/prefab/full/linux_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/28/e9/19563067a48a3a779d66bf19b606",
"build/prefab/full/linux_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/4c/3b/76d9dd64ac6a560eaccc3f86117e",
"build/prefab/full/linux_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/e0/06/a7297f3406ca0c21aad3caf2eb89",
"build/prefab/full/linux_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/d8/b3/5cf283436b598e8b30ff3bc85744",
"build/prefab/full/linux_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/9c/7b/ac1a200be0f37078af0991faca3b",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/10/2f/8b02f5434fd232a7cdfeab2701d4",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/e5/78/b289ab113be66c697ce64795193a",
"build/prefab/full/mac_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/17/54/7efe5b99d8588162ee757dea3348",
"build/prefab/full/mac_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/23/17/f1d541a3c9c3b5790e96828b7598",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/57/9f/d1bf09f5e0a2a15d730d9bb3c5cb",
"build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/d4/65/7a5e2941745c3036d89dbe3872de",
"build/prefab/full/mac_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/5b/d6/d740cfe4e8bbe21a5345df389454",
"build/prefab/full/mac_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/b1/ee/ea946bcdb77305710c59e9c6d128",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/70/f3/c4b89730342623be82e38f5f6ded",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/ac/f5/7ab6560338d20424f553ee33a940",
"build/prefab/full/windows_x86_gui/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/26/59/dfde2e6ce41ddfd89fa2e853db5c",
"build/prefab/full/windows_x86_gui/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/60/51/71851a9986828e22489227aee1ec",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/d8/b5/4bb7dfc057da66009868677f4131",
"build/prefab/full/windows_x86_server/release/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/5b/57/1d23e447aa72ee3e812171baa8df",
"build/prefab/lib/linux_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/e2/a9/6a5da77052000da6b35560120cd8",
"build/prefab/lib/linux_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/98/e4/199222439f5c1a9f4926aba0241b",
"build/prefab/lib/linux_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/69/bb/aabd8fa544c44831574d5b017ae7",
"build/prefab/lib/linux_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/f1/de/15cedd9462ef271415e9abccd06b",
"build/prefab/lib/linux_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/73/ee/290a65b39125abbb015415dc8b59",
"build/prefab/lib/linux_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/e8/0f/a6993b7e38a2d48e2a4938f4c4fd",
"build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/0b/93/5db13716ee4610ec88d409e3379d",
"build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/7a/34/1cda12f81c46067e7d6f9b74806e",
"build/prefab/lib/mac_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/4e/1e/a67f47468493a564f95f3218b999",
"build/prefab/lib/mac_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/d7/f0/41c098f285a9e5c76907c9547983",
"build/prefab/lib/mac_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/11/6e/e29738131f523b42168293c68d0d",
"build/prefab/lib/mac_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/7c/89/4af8bd76d718c306fd4cabe9b0b6",
"build/prefab/lib/mac_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/d8/62/c739869c92c06e35b8fd782a4fbc",
"build/prefab/lib/mac_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/90/53/c85bbfe89b765829b27c0d28617a",
"build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/f9/09/5a4922d34e314ef9ca8d4c90329d",
"build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/8d/de/025bb526c5a126636dffb011d5f4",
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/b8/e0/2277efb063810deba2967cb7c7e5",
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/98/32/72471c2f70116898b0dd01469951",
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/8f/24/8ca657c6df34919463278294fdcf",
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/31/ba/ceb77656d6670d6fa10ea45803f4",
"build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/e3/72/e5b82a0d6fafa4726784d0b4e950",
"build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/14/52/4c4d8e05d55133d6f144372fbb4c",
"build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/ef/ad/f9cda01f91ad9920324054cff7e7",
"build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/ce/a7/1ade386c868f6ef453eecbebacb7",
"build/prefab/full/linux_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/92/d4/532c645e24622e22523ecb9efe10",
"build/prefab/full/linux_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/f7/92/add1d8496f2d9ae7037862c2e6fb",
"build/prefab/full/mac_arm64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/52/d1/b3ca86d78477b50dcee97285269a",
"build/prefab/full/mac_arm64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/d1/76/2e120a6de7b1432878bc7267e4dd",
"build/prefab/full/mac_arm64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/55/a7/7b0e900785f82cf43251bf898937",
"build/prefab/full/mac_arm64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/81/e1/1f15d2b0bbffeb1023a72c695dc8",
"build/prefab/full/mac_x86_64_gui/debug/ballisticacore": "https://files.ballistica.net/cache/ba1/da/f0/bc3e7097aebf1c5062d60c1d5c70",
"build/prefab/full/mac_x86_64_gui/release/ballisticacore": "https://files.ballistica.net/cache/ba1/25/c1/343ac7e6e2103696ce941167e0b0",
"build/prefab/full/mac_x86_64_server/debug/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/26/44/aad33d56cc211dfa91307a111b8a",
"build/prefab/full/mac_x86_64_server/release/dist/ballisticacore_headless": "https://files.ballistica.net/cache/ba1/0a/78/723f2ee5ae737cd02257232d0729",
"build/prefab/full/windows_x86_gui/debug/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/f0/05/bf6283beadcb1795c1fe560f8e2e",
"build/prefab/full/windows_x86_gui/release/BallisticaCore.exe": "https://files.ballistica.net/cache/ba1/bd/14/91d70c343f8333e4effcda6c1c00",
"build/prefab/full/windows_x86_server/debug/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/ff/24/d6b24dc6916fd97dea6c66c02eea",
"build/prefab/full/windows_x86_server/release/dist/BallisticaCoreHeadless.exe": "https://files.ballistica.net/cache/ba1/8e/2f/5884adc4437b53661391c0f1dd8d",
"build/prefab/lib/linux_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/73/0f/0de5fda4c18b7ee322abf1e848ab",
"build/prefab/lib/linux_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/b8/9e/8ddc816e19d5e1c9c934ab70e1b3",
"build/prefab/lib/linux_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/b7/86/96f84ff68ebe8e14b110ebbd3012",
"build/prefab/lib/linux_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/c8/50/91a468ca1f2911f5ce3b0e3dcdfa",
"build/prefab/lib/linux_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/1c/b9/6afaa9f419844703351873fdc74e",
"build/prefab/lib/linux_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/21/da/5d5dec3a66f45ad4d8462665cf0b",
"build/prefab/lib/linux_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/63/3f/5d3738b98fbb02a2d9da441c893a",
"build/prefab/lib/linux_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/62/01/10294d07388877c4fef41aa3dffe",
"build/prefab/lib/mac_arm64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/b4/35/79eaa932393ca0c2aa434ce86a35",
"build/prefab/lib/mac_arm64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/c1/23/ae3ec5513b6fa4fb177dd275ff46",
"build/prefab/lib/mac_arm64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/43/9b/26a7a56f66a30c585d2f15ebe0d8",
"build/prefab/lib/mac_arm64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/65/5e/b1e78e47826aeb80a25cb1740f46",
"build/prefab/lib/mac_x86_64_gui/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/0e/8e/eee853378ffc62bb49c581d5b500",
"build/prefab/lib/mac_x86_64_gui/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/4b/67/c118ed2d8fe5c16574e7379b00e2",
"build/prefab/lib/mac_x86_64_server/debug/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/67/9d/384c2feeed57aa9c2a99ff4e866d",
"build/prefab/lib/mac_x86_64_server/release/libballisticacore_internal.a": "https://files.ballistica.net/cache/ba1/66/44/fff958ae6eed97d7a832354fc393",
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/9d/53/c505560ca72db28460cdea8ccb93",
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/64/4b/d067ff45b06e9aafd99a01170b65",
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/09/3e/874f0ff7ab9eadd5e23aa038730c",
"build/prefab/lib/windows/Debug_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/6e/03/4b7ed2a7f2486bf1a24fff8a4be1",
"build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.lib": "https://files.ballistica.net/cache/ba1/b1/54/4fb80db2c8e2aa28defaa4b99e12",
"build/prefab/lib/windows/Release_Win32/BallisticaCoreGenericInternal.pdb": "https://files.ballistica.net/cache/ba1/00/9c/cafd08dbf1b5ef98253dfe9db518",
"build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.lib": "https://files.ballistica.net/cache/ba1/c0/a1/b39dcb56feebe7d22f3aa7f53ee5",
"build/prefab/lib/windows/Release_Win32/BallisticaCoreHeadlessInternal.pdb": "https://files.ballistica.net/cache/ba1/dc/27/bca884b5d4db10c53eecead88baf",
"src/ballistica/generated/python_embedded/binding.inc": "https://files.ballistica.net/cache/ba1/f2/6c/5a0a4695dcc2a11e7941b8777e80",
"src/ballistica/generated/python_embedded/bootstrap.inc": "https://files.ballistica.net/cache/ba1/65/ac/d5c4162a71028c1bfa73ebc1f881"
}

View File

@ -2,6 +2,7 @@
- Added co-op support to server builds (thanks Dliwk!)
- Updated everything from Python 3.8 to Python 3.9. The biggest immediate impact to our code is that basic types such as list, dict, and tuple can be used in annotations, eliminating the need to import typing.Dict, typing.List, etc. See python.org for more changes.
- Note: accessing mods on external storage on Android will not work in this release. This functionality has not been working in recent versions of Android due to increased security features anyway and I am in the process of replacing it with a cloud based system for installing mods. More on this soon.
- Python 3.9 no longer supports Windows 7 or earlier (according to https://www.python.org/downloads/windows/) so if you are running such a version of Windows you will need to stick to older builds.
### 1.6.4 (20382)
- Some cleanups in the Favorites tab of the gather window.

View File

@ -312,6 +312,7 @@ add_executable(ballisticacore
${BA_SRC_ROOT}/ballistica/game/game.cc
${BA_SRC_ROOT}/ballistica/game/game.h
${BA_SRC_ROOT}/ballistica/game/game_stream.h
${BA_SRC_ROOT}/ballistica/game/host_activity.cc
${BA_SRC_ROOT}/ballistica/game/host_activity.h
${BA_SRC_ROOT}/ballistica/game/player.cc
${BA_SRC_ROOT}/ballistica/game/player.h

View File

@ -0,0 +1,529 @@
// Released under the MIT License. See LICENSE for details.
#include "ballistica/game/host_activity.h"
#include "ballistica/dynamics/material/material.h"
#include "ballistica/game/game_stream.h"
#include "ballistica/game/player.h"
#include "ballistica/game/session/host_session.h"
#include "ballistica/generic/timer.h"
#include "ballistica/input/device/input_device.h"
#include "ballistica/media/component/collide_model.h"
#include "ballistica/media/component/data.h"
#include "ballistica/media/component/model.h"
#include "ballistica/media/component/sound.h"
#include "ballistica/media/component/texture.h"
#include "ballistica/python/python.h"
#include "ballistica/python/python_context_call.h"
#include "ballistica/python/python_sys.h"
#include "ballistica/scene/node/globals_node.h"
#include "ballistica/scene/node/node_type.h"
namespace ballistica {
HostActivity::HostActivity(HostSession* host_session) {
// Store a link to the HostSession and add ourself to it.
host_session_ = host_session;
// Create our game timer - gets called whenever game should step.
step_scene_timer_ =
base_timers_.NewTimer(base_time_, kGameStepMilliseconds, 0, -1,
NewLambdaRunnable([this] { StepScene(); }));
SetGameSpeed(1.0f);
{
ScopedSetContext cp(this); // So scene picks us up as context.
scene_ = Object::New<Scene>(0);
// If there's an output stream, add to it.
if (GameStream* out = host_session->GetGameStream()) {
out->AddScene(scene_.get());
}
}
}
HostActivity::~HostActivity() {
shutting_down_ = true;
// Put the scene in shut-down mode before we start killing stuff.
// (this generates warnings, suppresses messages, etc)
scene_->set_shutting_down(true);
// Clear out all python calls registered in our context.
// (should wipe out refs to our activity and prevent them from running without
// a valid activity context)
for (auto&& i : python_calls_) {
if (i.exists()) {
i->MarkDead();
}
}
// Mark all our media dead to clear it out of our output-stream cleanly
for (auto&& i : textures_) {
if (i.second.exists()) {
i.second->MarkDead();
}
}
for (auto&& i : models_) {
if (i.second.exists()) {
i.second->MarkDead();
}
}
for (auto&& i : sounds_) {
if (i.second.exists()) {
i.second->MarkDead();
}
}
for (auto&& i : collide_models_) {
if (i.second.exists()) {
i.second->MarkDead();
}
}
for (auto&& i : materials_) {
if (i.exists()) {
i->MarkDead();
}
}
// Clear our timers and scene; this should wipe out any remaining refs to our
// python activity, allowing it to die.
base_timers_.Clear();
sim_timers_.Clear();
scene_.Clear();
// Report outstanding calls. There shouldn't be any at this point. Actually it
// turns out there's generally 1; whichever call was responsible for killing
// this activity will still be in progress.. so let's report on 2 or more I
// guess.
if (g_buildconfig.debug_build()) {
PruneDeadRefs(&python_calls_);
if (python_calls_.size() > 1) {
std::string s = "WARNING: " + std::to_string(python_calls_.size())
+ " live PythonContextCalls at shutdown for "
+ "HostActivity" + " (1 call is expected):";
int count = 1;
for (auto& python_call : python_calls_)
s += "\n " + std::to_string(count++) + ": "
+ (*python_call).GetObjectDescription();
Log(s);
}
}
}
auto HostActivity::GetGameStream() const -> GameStream* {
if (!host_session_.exists()) return nullptr;
return host_session_->GetGameStream();
}
auto HostActivity::SetGlobalsNode(GlobalsNode* node) -> void {
globals_node_ = node;
}
void HostActivity::StepScene() {
int cycle_count = 1;
if (host_session_->benchmark_type() == BenchmarkType::kCPU) {
cycle_count = 100;
}
for (int cycle = 0; cycle < cycle_count; ++cycle) {
assert(InGameThread());
// Clear our player-positions for this step.
// FIXME: Move this to scene and/or player node.
assert(host_session_.exists());
for (auto&& player : host_session_->players()) {
assert(player.exists());
player->set_have_position(false);
}
// Run our sim-time timers.
sim_timers_.Run(scene()->time());
// Send die-messages/etc to out-of-bounds stuff.
HandleOutOfBoundsNodes();
scene()->Step();
}
}
void HostActivity::RegisterCall(PythonContextCall* call) {
assert(call);
python_calls_.emplace_back(call);
// If we're shutting down, just kill the call immediately.
// (we turn all of our calls to no-ops as we shut down)
if (shutting_down_) {
Log("WARNING: adding call to expired activity; call will not function: "
+ call->GetObjectDescription());
call->MarkDead();
}
}
void HostActivity::start() {
if (_started) {
Log("Error: Start called twice for activity.");
}
_started = true;
}
auto HostActivity::GetAsHostActivity() -> HostActivity* { return this; }
auto HostActivity::NewMaterial(const std::string& name)
-> Object::Ref<Material> {
if (shutting_down_) {
throw Exception("can't create materials during activity shutdown");
}
auto m(Object::New<Material>(name, scene()));
materials_.emplace_back(m);
return m;
}
auto HostActivity::GetTexture(const std::string& name) -> Object::Ref<Texture> {
if (shutting_down_) {
throw Exception("can't load assets during activity shutdown");
}
return Media::GetMedia(&textures_, name, scene());
}
auto HostActivity::GetSound(const std::string& name) -> Object::Ref<Sound> {
if (shutting_down_) {
throw Exception("can't load assets during activity shutdown");
}
return Media::GetMedia(&sounds_, name, scene());
}
auto HostActivity::GetData(const std::string& name) -> Object::Ref<Data> {
if (shutting_down_) {
throw Exception("can't load assets during activity shutdown");
}
return Media::GetMedia(&datas_, name, scene());
}
auto HostActivity::GetModel(const std::string& name) -> Object::Ref<Model> {
if (shutting_down_) {
throw Exception("can't load assets during activity shutdown");
}
return Media::GetMedia(&models_, name, scene());
}
auto HostActivity::GetCollideModel(const std::string& name)
-> Object::Ref<CollideModel> {
if (shutting_down_) {
throw Exception("can't load assets during activity shutdown");
}
return Media::GetMedia(&collide_models_, name, scene());
}
void HostActivity::SetPaused(bool val) {
if (paused_ == val) {
return;
}
paused_ = val;
UpdateStepTimerLength();
}
void HostActivity::SetGameSpeed(float speed) {
if (speed == game_speed_) {
return;
}
assert(speed >= 0.0f);
game_speed_ = speed;
UpdateStepTimerLength();
}
void HostActivity::UpdateStepTimerLength() {
if (game_speed_ == 0.0f || paused_) {
step_scene_timer_->SetLength(-1, true, base_time_);
} else {
step_scene_timer_->SetLength(
std::max(1, static_cast<int>(
round(static_cast<float>(kGameStepMilliseconds)
/ (game_speed_ * g_game->debug_speed_mult())))),
true, base_time_);
}
}
void HostActivity::HandleOutOfBoundsNodes() {
if (scene()->out_of_bounds_nodes().empty()) {
out_of_bounds_in_a_row_ = 0;
return;
}
// Make sure someone's handling our out-of-bounds messages.
out_of_bounds_in_a_row_++;
if (out_of_bounds_in_a_row_ > 100) {
Log("Warning: 100 consecutive out-of-bounds messages sent."
" They are probably not being handled properly");
int j = 0;
for (auto&& i : scene()->out_of_bounds_nodes()) {
j++;
Node* n = i.get();
if (n) {
std::string dstr;
PyObject* delegate = n->GetDelegate();
if (delegate) {
dstr = PythonRef(delegate, PythonRef::kAcquire).Str();
}
Log(" node #" + std::to_string(j) + ": type='" + n->type()->name()
+ "' addr=" + Utils::PtrToString(i.get()) + " name='" + n->label()
+ "' delegate=" + dstr);
}
}
out_of_bounds_in_a_row_ = 0;
}
// Send out-of-bounds messages to newly out-of-bounds nodes.
for (auto&& i : scene()->out_of_bounds_nodes()) {
Node* n = i.get();
if (n) {
n->DispatchOutOfBoundsMessage();
}
}
}
void HostActivity::RegisterPyActivity(PyObject* pyActivityObj) {
assert(pyActivityObj && pyActivityObj != Py_None);
assert(!py_activity_weak_ref_.exists());
// Store a python weak-ref to this activity.
py_activity_weak_ref_.Steal(PyWeakref_NewRef(pyActivityObj, nullptr));
}
auto HostActivity::GetPyActivity() const -> PyObject* {
PyObject* obj = py_activity_weak_ref_.get();
if (!obj) return Py_None;
return PyWeakref_GetObject(obj);
}
auto HostActivity::GetHostSession() -> HostSession* {
return host_session_.get();
}
auto HostActivity::GetMutableScene() -> Scene* {
Scene* sg = scene_.get();
assert(sg);
return sg;
}
void HostActivity::SetIsForeground(bool val) {
// If we're foreground, set our scene as foreground.
Scene* sg = scene();
if (val && sg) {
// Set it locally.
g_game->SetForegroundScene(sg);
// Also push it to clients.
if (GameStream* out = GetGameStream()) {
out->SetForegroundScene(scene_.get());
}
}
}
auto HostActivity::globals_node() const -> GlobalsNode* {
return globals_node_.get();
}
auto HostActivity::NewSimTimer(millisecs_t length, bool repeat,
const Object::Ref<Runnable>& runnable) -> int {
if (shutting_down_) {
BA_LOG_PYTHON_TRACE_ONCE(
"WARNING: Creating game timer during host-activity shutdown");
return 123; // Dummy.
}
if (length == 0 && repeat) {
throw Exception("Can't add game-timer with length 0 and repeat on");
}
if (length < 0) {
throw Exception("Timer length cannot be < 0 (got " + std::to_string(length)
+ ")");
}
int offset = 0;
Timer* t = sim_timers_.NewTimer(scene()->time(), length, offset,
repeat ? -1 : 0, runnable);
return t->id();
}
auto HostActivity::NewBaseTimer(millisecs_t length, bool repeat,
const Object::Ref<Runnable>& runnable) -> int {
if (shutting_down_) {
BA_LOG_PYTHON_TRACE_ONCE(
"WARNING: Creating session-time timer during host-activity shutdown");
return 123; // dummy...
}
if (length == 0 && repeat) {
throw Exception("Can't add session-time timer with length 0 and repeat on");
}
if (length < 0) {
throw Exception("Timer length cannot be < 0");
}
int offset = 0;
Timer* t = base_timers_.NewTimer(base_time_, length, offset, repeat ? -1 : 0,
runnable);
return t->id();
}
void HostActivity::DeleteSimTimer(int timer_id) {
assert(InGameThread());
if (shutting_down_) return;
sim_timers_.DeleteTimer(timer_id);
}
void HostActivity::DeleteBaseTimer(int timer_id) {
assert(InGameThread());
if (shutting_down_) return;
base_timers_.DeleteTimer(timer_id);
}
auto HostActivity::Update(millisecs_t time_advance) -> millisecs_t {
assert(InGameThread());
// We can be killed at any time, so let's keep an eye out for that.
WeakRef<HostActivity> test_ref(this);
assert(test_ref.exists());
// If we haven't been told to start yet, don't do anything more.
if (!_started) {
return 1000;
}
// Advance base time by the specified amount, stopping at all timers along the
// way.
millisecs_t target_base_time = base_time_ + time_advance;
while (!base_timers_.empty()
&& (base_time_ + base_timers_.GetTimeToNextExpire(base_time_)
<= target_base_time)) {
base_time_ += base_timers_.GetTimeToNextExpire(base_time_);
base_timers_.Run(base_time_);
if (!test_ref.exists()) {
return 1000; // The last timer run might have killed us.
}
}
base_time_ = target_base_time;
// Periodically prune various dead refs.
if (base_time_ > next_prune_time_) {
PruneDeadMapRefs(&textures_);
PruneDeadMapRefs(&sounds_);
PruneDeadMapRefs(&collide_models_);
PruneDeadMapRefs(&models_);
PruneDeadRefs(&materials_);
PruneDeadRefs(&python_calls_);
next_prune_time_ = base_time_ + 5000;
}
// Return the time until the next timer goes off.
return base_timers_.empty() ? 1000
: base_timers_.GetTimeToNextExpire(base_time_);
}
void HostActivity::ScreenSizeChanged() { scene()->ScreenSizeChanged(); }
void HostActivity::LanguageChanged() { scene()->LanguageChanged(); }
void HostActivity::DebugSpeedMultChanged() { UpdateStepTimerLength(); }
void HostActivity::GraphicsQualityChanged(GraphicsQuality q) {
scene()->GraphicsQualityChanged(q);
}
void HostActivity::Draw(FrameDef* frame_def) {
if (!_started) return;
scene()->Draw(frame_def);
}
void HostActivity::DumpFullState(GameStream* out) {
// Add our scene.
if (scene_.exists()) {
scene_->Dump(out);
}
// Before doing any nodes, we need to create all materials.
// (but *not* their components, which may reference the nodes that we haven't
// made yet)
for (auto&& i : materials_) {
if (Material* m = i.get()) {
out->AddMaterial(m);
}
}
// Add our media.
for (auto&& i : textures_) {
if (Texture* t = i.second.get()) {
out->AddTexture(t);
}
}
for (auto&& i : sounds_) {
if (Sound* s = i.second.get()) {
out->AddSound(s);
}
}
for (auto&& i : models_) {
if (Model* s = i.second.get()) {
out->AddModel(s);
}
}
for (auto&& i : collide_models_) {
if (CollideModel* m = i.second.get()) {
out->AddCollideModel(m);
}
}
// Add scene's nodes.
if (scene_.exists()) {
scene_->DumpNodes(out);
}
// Ok, now we can fill out our materials since nodes/etc they reference
// exists.
for (auto&& i : materials_) {
if (Material* m = i.get()) {
m->DumpComponents(out);
}
}
}
auto HostActivity::NewTimer(TimeType timetype, TimerMedium length, bool repeat,
const Object::Ref<Runnable>& runnable) -> int {
// Make sure the runnable passed in is reference-managed already.
// (we may not add an initial reference ourself)
assert(runnable->is_valid_refcounted_object());
// We currently support game and base timers.
switch (timetype) {
case TimeType::kSim:
return NewSimTimer(length, repeat, runnable);
case TimeType::kBase:
return NewBaseTimer(length, repeat, runnable);
default:
// Fall back to default for descriptive error otherwise.
return ContextTarget::NewTimer(timetype, length, repeat, runnable);
}
}
void HostActivity::DeleteTimer(TimeType timetype, int timer_id) {
switch (timetype) {
case TimeType::kSim:
DeleteSimTimer(timer_id);
break;
case TimeType::kBase:
DeleteBaseTimer(timer_id);
break;
default:
// Fall back to default for descriptive error otherwise.
ContextTarget::DeleteTimer(timetype, timer_id);
break;
}
}
auto HostActivity::GetTime(TimeType timetype) -> millisecs_t {
switch (timetype) {
case TimeType::kSim:
return scene()->time();
case TimeType::kBase:
return base_time();
default:
// Fall back to default for descriptive error otherwise.
return ContextTarget::GetTime(timetype);
}
}
} // namespace ballistica