# Released under the MIT License. See LICENSE for details.
#
"""A dummy stub module for the real _bascenev1.
The real _bascenev1 is a compiled extension module and only available
in the live engine. This dummy-module allows Pylint/Mypy/etc. to
function reasonably well outside of that environment.
Make sure this file is never included in dirs seen by the engine!
In the future perhaps this can be a stub (.pyi) file, but we will need
to make sure that it works with all our tools (mypy, pylint).
NOTE: This file was autogenerated by batools.dummymodule; do not edit by hand.
"""
from __future__ import annotations # Docs-generation hack.
# I'm sorry Pylint. I know this file saddens you. Be strong.
# pylint: disable=useless-suppression
# pylint: disable=unnecessary-pass
# pylint: disable=use-dict-literal
# pylint: disable=use-list-literal
# pylint: disable=unused-argument
# pylint: disable=missing-docstring
# pylint: disable=too-many-locals
# pylint: disable=redefined-builtin
# pylint: disable=too-many-lines
# pylint: disable=redefined-outer-name
# pylint: disable=invalid-name
# pylint: disable=no-value-for-parameter
# pylint: disable=unused-import
# pylint: disable=too-many-positional-arguments
from typing import TYPE_CHECKING, overload, override, Sequence
from warnings import deprecated
if TYPE_CHECKING:
from typing import Any, Callable, Literal
import babase
import bascenev1
import bauiv1
def _uninferrable() -> Any:
"""Get an "Any" in mypy and "uninferrable" in Pylint."""
# pylint: disable=undefined-variable
return _not_a_real_variable # type: ignore
class ActivityData:
"""Internal; holds native data for the activity.
:meta private:
"""
def context(self) -> bascenev1.ContextRef:
"""Return a context-ref pointing to the activity."""
# This is a dummy stub; the actual implementation is native code.
import bascenev1 # pylint: disable=cyclic-import
return bascenev1.ContextRef()
def exists(self) -> bool:
"""Returns whether the activity-data still exists.
Most functionality will fail on a nonexistent instance.
"""
# This is a dummy stub; the actual implementation is native code.
return bool()
def expire(self) -> None:
"""Expires the internal data for the activity"""
# This is a dummy stub; the actual implementation is native code.
return None
def make_foreground(self) -> None:
"""Sets this activity as the foreground one in its session."""
# This is a dummy stub; the actual implementation is native code.
return None
def start(self) -> None:
"""Begins the activity running"""
# This is a dummy stub; the actual implementation is native code.
return None
[docs]
class BaseTimer:
"""Timers are used to run code at later points in time.
This class encapsulates a base-time timer in the current scene
context.
The underlying timer will be destroyed when either this object is
no longer referenced or when its context (activity, etc.) dies. If you
do not want to worry about keeping a reference to your timer around,
you should use the :meth:`bascenev1.basetimer()` function instead.
Args:
time:
Length of time in seconds that the timer will wait
before firing.
call:
A callable Python object. Remember that the timer will retain a
strong reference to the callable for as long as it exists, so you
may want to look into concepts such as :class:`~babase.WeakCall`
if that is not desired.
repeat:
If True, the timer will fire repeatedly, with each successive
firing having the same delay as the first.
Example
-------
Use a base-timer object to print repeatedly for a few seconds::
import bascenev1 as bs
def say_it():
bs.screenmessage('BADGER!')
def stop_saying_it():
global g_timer
g_timer = None
bs.screenmessage('MUSHROOM MUSHROOM!')
# Create our timer; it will run as long as we keep its ref alive.
g_timer = bs.BaseTimer(0.3, say_it, repeat=True)
# Now fire off a one-shot timer to kill the ref.
bs.basetimer(3.89, stop_saying_it)
"""
def __init__(
self, time: float, call: Callable[[], Any], repeat: bool = False
) -> None:
pass
[docs]
class CollisionMesh:
"""A reference to a collision-mesh.
Use :meth:`bascenev1.getcollisionmesh()` to instantiate one.
"""
pass
[docs]
class Data:
"""A reference to a data object.
Use :meth:`bascenev1.getdata()` to instantiate one.
"""
[docs]
def getvalue(self) -> Any:
"""Return the data object's value.
This can consist of anything representable by json (dicts, lists,
numbers, bools, None, etc).
Note that this call will block if the data has not yet been loaded,
so it can be beneficial to plan a short bit of time between when
the data object is requested and when it's value is accessed.
"""
# This is a dummy stub; the actual implementation is native code.
return _uninferrable()
[docs]
class Depiction:
"""A depiction registered in a scene, for nodes to show.
Built from a json-serialized :class:`bacommon.depiction.Depiction`
(a name, a character's icon, ...) and assigned to node attrs of
the depiction type (a ``depictiondisplay`` node's ``depiction``,
say). It crosses the stream once however many nodes show it;
every machine draws it natively, as a placeholder if it can't.
Lifetime works like :class:`Material`: the depiction lives as
long as something references it (this object or a node attr)
and leaves the session automatically once nothing does.
Must be created in a host activity or host session context, and
can only be assigned to nodes of that same scene (scene objects
never cross scenes; the session's lobby has its own). To show
the same thing in another activity, build another from the same
json there.
"""
def __init__(self, json: str) -> None:
pass
[docs]
class Material:
"""An entity applied to game objects to modify collision behavior.
A material can affect physical characteristics, generate sounds,
or trigger callback functions when collisions occur.
Materials are applied to 'parts', which are groups of one or more
rigid bodies created as part of a bascenev1.Node. Nodes can have any
number of parts, each with its own set of materials. Generally
materials are specified as array attributes on the Node. The `spaz`
node, for example, has various attributes such as `materials`,
`roller_materials`, and `punch_materials`, which correspond
to the various parts it creates.
Use bascenev1.Material to instantiate a blank material, and then use
its :meth:`bascenev1.Material.add_actions()` method to define what the
material does.
"""
def __init__(self, label: str | None = None) -> None:
pass
#: A label for the material; only used for debugging.
label: str
[docs]
def add_actions(
self, actions: tuple, conditions: tuple | None = None
) -> None:
"""Add one or more actions to the material, optionally with conditions.
Conditions
==========
Conditions are provided as tuples which can be combined to form
boolean logic. A single condition might look like:
``('condition_name', cond_arg)``
Or a more complex nested one might look like:
``(('condition1', cond_arg), 'or', ('condition2', cond2_arg))``
The strings ``'and'``, ``'or'``, and ``'xor'`` can chain together
two conditions, as seen above.
Available Conditions
--------------------
``('they_have_material', material)``
Does the part we're hitting have a given
:class:`bascenev1.Material`?
``('they_dont_have_material', material)``
Does the part we're hitting not have a given
:class:`bascenev1.Material`?
``('eval_colliding')``
Is ``'collide'`` true at this point
in material evaluation? (see the ``modify_part_collision`` action)
``('eval_not_colliding')``
Is ``collide`` false at this point
in material evaluation? (see the ``modify_part_collision`` action)
``('we_are_younger_than', age)``
Is our part younger than ``age`` (in milliseconds)?
``('we_are_older_than', age)``
Is our part older than ``age`` (in milliseconds)?
``('they_are_younger_than', age)``
Is the part we're hitting younger than ``age`` (in milliseconds)?
``('they_are_older_than', age)``
Is the part we're hitting older than ``age`` (in milliseconds)?
``('they_are_same_node_as_us')``
Does the part we're hitting belong to the same
:class:`bascenev1.Node`
as us?
``('they_are_different_node_than_us')``
Does the part we're hitting belong to a different
:class:`bascenev1.Node`?
Actions
=======
In a similar manner, actions are specified as tuples. Multiple
actions can be specified by providing a tuple of tuples.
Available Actions
-----------------
``('call', when, callable)``
Calls the provided callable;
``when`` can be either ``'at_connect'`` or ``'at_disconnect'``.
``'at_connect'`` means to fire when the two parts first come in
contact; ``'at_disconnect'`` means to fire once they cease being
in contact.
``('message', who, when, message_obj)``
Sends a message object; ``who`` can be either ``'our_node'`` or
``'their_node'``, ``when`` can be ``'at_connect'`` or
``'at_disconnect'``, and ``message_obj`` is the message object to
send. This has the same effect as calling the node's
:meth:`bascenev1.Node.handlemessage()` method.
``('modify_part_collision', attr, value)``
Changes some characteristic of the physical collision that will
occur between our part and their part. This change will remain in
effect as long as the two parts remain overlapping. This means if
you have a part with a material that turns ``'collide'`` off
against parts younger than 100ms, and it touches another part that
is 50ms old, it will continue to not collide with that part until
they separate, even if the 100ms threshold is passed. Options for
attr/value are:
``'physical'`` (boolean value; whether a *physical* response will
occur at all), ``'friction'`` (float value; how friction-y the
physical response will be), ``'collide'`` (boolean value;
whether *any* collision will occur at all, including non-physical
stuff like callbacks), ``'use_node_collide'``
(boolean value; whether to honor modify_node_collision
overrides for this collision), ``'stiffness'`` (float value,
how springy the physical response is), ``'damping'`` (float
value, how damped the physical response is), ``'bounce'`` (float
value; how bouncy the physical response is).
``('modify_node_collision', attr, value)``
Similar to ``modify_part_collision``, but operates at a
node-level. Collision attributes set here will remain in effect
as long as *anything* from our part's node and their part's node
overlap. A key use of this functionality is to prevent new nodes
from colliding with each other if they appear overlapped;
if ``modify_part_collision`` is used, only the individual
parts that were overlapping would avoid contact, but other parts
could still contact leaving the two nodes 'tangled up'. Using
``modify_node_collision`` ensures that the nodes must completely
separate before they can start colliding. Currently the only attr
available here is ``'collide'`` (a boolean value).
``('sound', sound, volume)``
Plays a :class:`bascenev1.Sound` when a collision occurs, at a
given volume, regardless of the collision speed/etc.
``('impact_sound', sound, target_impulse, volume)``
Plays a sound when a collision occurs, based on the speed of
impact. Provide a :class:`bascenev1.Sound`, a target-impulse,
and a volume.
``('skid_sound', sound, target_impulse, volume)``
Plays a sound during a collision when parts are 'scraping'
against each other. Provide a :class:`bascenev1.Sound`,
a target-impulse, and a volume.
``('roll_sound', sound, targetImpulse, volume)``
Plays a sound during a collision when parts are 'rolling'
against each other.
Provide a :class:`bascenev1.Sound`, a target-impulse, and a
volume.
Examples
========
**Example 1:** Create a material that lets us ignore
collisions against any nodes we touch in the first
100 ms of our existence; handy for preventing us from
exploding outward if we spawn on top of another object::
m = bascenev1.Material()
m.add_actions(
conditions=(('we_are_younger_than', 100),
'or', ('they_are_younger_than', 100)),
actions=('modify_node_collision', 'collide', False))
**Example 2:** Send a :class:`bascenev1.DieMessage` to anything we
touch, but cause no physical response. This should cause any
:class:`bascenev1.Actor` to drop dead::
m = bascenev1.Material()
m.add_actions(
actions=(
('modify_part_collision', 'physical', False),
('message', 'their_node', 'at_connect', bascenev1.DieMessage())
)
)
**Example 3:** Play some sounds when we're contacting the
ground::
m = bascenev1.Material()
m.add_actions(
conditions=('they_have_material' shared.footing_material),
actions=(
('impact_sound', bascenev1.getsound('metalHit'), 2, 5),
('skid_sound', bascenev1.getsound('metalSkid'), 2, 5)
)
)
"""
# This is a dummy stub; the actual implementation is native code.
return None
[docs]
class Mesh:
"""A reference to a mesh.
Meshes are used for drawing.
Use :meth:`bascenev1.getmesh()` to instantiate one.
"""
pass
[docs]
class Node:
"""Reference to a Node; the low level building block of a game.
At its core, a game is nothing more than a scene of Nodes
with attributes getting interconnected or set over time.
A :class:`bascenev1.Node` instance should be thought of as a
weak-reference to a game node; *not* the node itself. This means
a Node's lifecycle is completely independent of how many Python
references to it exist. To explicitly add a new node to the game, use
:meth:`bascenev1.newnode()`, and to explicitly delete one, use
:meth:`bascenev1.Node.delete()`.
:meth:`bascenev1.Node.exists()` can be used to determine if a Node
still points to a live node in the game.
You can use ``bascenev1.Node(None)`` to instantiate an invalid
Node reference (sometimes used as attr values/etc).
"""
# Note attributes:
# NOTE: I'm just adding *all* possible node attrs here
# now now since we have a single bascenev1.Node type; in the
# future I hope to create proper individual classes
# corresponding to different node types with correct
# attributes per node-type.
color: Sequence[float] = (0.0, 0.0, 0.0)
size: Sequence[float] = (0.0, 0.0, 0.0)
position: Sequence[float] = (0.0, 0.0, 0.0)
position_center: Sequence[float] = (0.0, 0.0, 0.0)
position_forward: Sequence[float] = (0.0, 0.0, 0.0)
punch_position: Sequence[float] = (0.0, 0.0, 0.0)
punch_velocity: Sequence[float] = (0.0, 0.0, 0.0)
velocity: Sequence[float] = (0.0, 0.0, 0.0)
name_color: Sequence[float] = (0.0, 0.0, 0.0)
tint_color: Sequence[float] = (0.0, 0.0, 0.0)
tint2_color: Sequence[float] = (0.0, 0.0, 0.0)
tint3_color: Sequence[float] = (0.0, 0.0, 0.0)
text: babase.Lstr | babase.LangStr | str = ''
suffix: babase.Lstr | babase.LangStr | str = ''
color_override: Sequence[float] = (1.0, 1.0, 1.0)
use_color_override: bool = False
brightness: float = 1.0
texture: bascenev1.Texture | None = None
tint_texture: bascenev1.Texture | None = None
spaz_def: bascenev1.SpazDef | None = None
depiction: bascenev1.Depiction | None = None
times: Sequence[int] = (1, 2, 3, 4, 5)
values: Sequence[float] = (1.0, 2.0, 3.0, 4.0)
offset: float = 0.0
input0: float = 0.0
input1: float = 0.0
input2: float = 0.0
input3: float = 0.0
flashing: bool = False
flash: bool = False
scale: float | Sequence[float] = 0.0
opacity: float = 0.0
loop: bool = False
time1: int = 0
time2: int = 0
timemax: int = 0
client_only: bool = False
materials: Sequence[bascenev1.Material] = ()
roller_materials: Sequence[bascenev1.Material] = ()
name: str = ''
punch_materials: Sequence[bascenev1.Material] = ()
pickup_materials: Sequence[bascenev1.Material] = ()
extras_material: Sequence[bascenev1.Material] = ()
rotate: float | Sequence[float] = 0.0
hold_node: bascenev1.Node | None = None
hold_body: int = 0
behavior_version: int = 0
pickup_before_hitbox: bool = False
pickup_release_time_ms: float = 0
host_only: bool = False
visible: bool = True
config: str = ''
premultiplied: bool = False
source_player: bascenev1.Player | None = None
mesh_opaque: bascenev1.Mesh | None = None
mesh_transparent: bascenev1.Mesh | None = None
damage_smoothed: float = 0.0
gravity_scale: float = 1.0
punch_power: float = 0.0
punch_momentum_linear: Sequence[float] = (0.0, 0.0, 0.0)
punch_momentum_angular: float = 0.0
rate: int = 0
vr_depth: float = 0.0
is_area_of_interest: bool = False
jump_pressed: bool = False
pickup_pressed: bool = False
punch_pressed: bool = False
bomb_pressed: bool = False
fly_pressed: bool = False
hold_position_pressed: bool = False
#: Available on spaz node.
knockout: float = 0.0
invincible: bool = False
stick_to_owner: bool = False
stickiness: float = 1.0
damage: int = 0
#: Available on spaz node.
run: float = 0.0
#: Available on spaz node.
move_up_down: float = 0.0
#: Available on spaz node.
move_left_right: float = 0.0
curse_death_time: int = 0
boxing_gloves: bool = False
hockey: bool = False
use_fixed_vr_overlay: bool = False
#: Available on globals node.
allow_kick_idle_players: bool = False
legacy_spaz_limbs: bool = False
music_continuous: bool = False
music_count: int = 0
#: Available on spaz node.
hurt: float = 0.0
#: On shield node. Only consulted while health_bar_display
#: is :attr:`bascenev1.HealthBarDisplay.DEFAULT`.
always_show_health_bar: bool = False
#: On shield node; a :class:`bascenev1.HealthBarDisplay` value.
health_bar_display: int = 0
#: Available on spaz node.
mini_billboard_1_texture: bascenev1.Texture | None = None
#: Available on spaz node.
mini_billboard_1_start_time: int = 0
#: Available on spaz node.
mini_billboard_1_end_time: int = 0
#: Available on spaz node.
mini_billboard_2_texture: bascenev1.Texture | None = None
#: Available on spaz node.
mini_billboard_2_start_time: int = 0
#: Available on spaz node.
mini_billboard_2_end_time: int = 0
#: Available on spaz node.
mini_billboard_3_texture: bascenev1.Texture | None = None
#: Available on spaz node.
mini_billboard_3_start_time: int = 0
#: Available on spaz node.
mini_billboard_3_end_time: int = 0
#: Available on spaz node.
boxing_gloves_flashing: bool = False
#: Available on spaz node.
dead: bool = False
floor_reflection: bool = False
debris_friction: float = 0.0
debris_kill_height: float = 0.0
vr_near_clip: float = 0.0
shadow_ortho: bool = False
happy_thoughts_mode: bool = False
shadow_offset: Sequence[float] = (0.0, 0.0)
paused: bool = False
time: int = 0
ambient_color: Sequence[float] = (1.0, 1.0, 1.0)
camera_mode: str = 'rotate'
frozen: bool = False
area_of_interest_bounds: Sequence[float] = (-1, -1, -1, 1, 1, 1)
shadow_range: Sequence[float] = (0, 0, 0, 0)
counter_text: str = ''
counter_texture: bascenev1.Texture | None = None
#: Available on spaz node.
shattered: int = 0
#: Available on spaz node.
billboard_texture: bascenev1.Texture | None = None
#: Available on spaz node.
billboard_cross_out: bool = False
#: Available on spaz node.
billboard_opacity: float = 0.0
#: Available on spaz node.
use_spaz_def_color: bool = False
#: Available on spaz node.
use_spaz_def_highlight: bool = False
#: Available on spaz and depictiondisplay nodes.
team_coloring: bool = False
#: Available on spaz node.
boxing_gloves_mesh: bascenev1.Mesh | None = None
#: Available on spaz node.
boxing_gloves_color_texture: bascenev1.Texture | None = None
#: Available on spaz node.
boxing_gloves_color: Sequence[float] = (1.0, 1.0, 1.0)
#: Available on spaz node.
boxing_gloves_scale: float = 1.0
slow_motion: bool = False
music: str = ''
vr_camera_offset: Sequence[float] = (0.0, 0.0, 0.0)
vr_overlay_center: Sequence[float] = (0.0, 0.0, 0.0)
vr_overlay_center_enabled: bool = False
vignette_outer: Sequence[float] = (0.0, 0.0)
vignette_inner: Sequence[float] = (0.0, 0.0)
tint: Sequence[float] = (1.0, 1.0, 1.0)
def __bool__(self) -> bool:
"""Support for bool evaluation."""
return bool(True) # Slight obfuscation.
[docs]
def add_death_action(self, action: Callable[[], None]) -> None:
"""Add a callable object to be called upon this node's death.
Note that these actions are run just after the node dies, not before.
"""
# This is a dummy stub; the actual implementation is native code.
return None
[docs]
def connectattr(self, srcattr: str, dstnode: Node, dstattr: str) -> None:
"""Connect one of this node's attributes to an attribute on another
node. This will immediately set the target attribute's value to that
of the source attribute, and will continue to do so once per step
as long as the two nodes exist. The connection can be severed by
setting the target attribute to any value or connecting another
node attribute to it.
Example: Create a locator and attach a light to it::
light = bascenev1.newnode('light')
loc = bascenev1.newnode('locator', attrs={'position': (0, 10, 0)})
loc.connectattr('position', light, 'position')
"""
# This is a dummy stub; the actual implementation is native code.
return None
[docs]
def delete(self, ignore_missing: bool = True) -> None:
"""Delete the node. Ignores already-deleted nodes if `ignore_missing`
is True; otherwise a :class:`babase.NodeNotFoundError` is thrown.
"""
# This is a dummy stub; the actual implementation is native code.
return None
[docs]
def exists(self) -> bool:
"""Returns whether the Node still exists.
Most functionality will fail on a nonexistent Node, so it's never a bad
idea to check this.
Note that you can also use the boolean operator for this same
functionality, so a statement such as "if mynode" will do
the right thing both for Node objects and values of None.
"""
# This is a dummy stub; the actual implementation is native code.
return bool()
# Show that ur return type varies based on "doraise" value:
@overload
def getdelegate[T](
self, type: type[T], doraise: Literal[False] = False
) -> T | None: ...
@overload
def getdelegate[T](self, type: type[T], doraise: Literal[True]) -> T: ...
[docs]
def getdelegate(self, type: Any, doraise: bool = False) -> Any:
"""Return the node's current delegate object if it matches
a certain type.
If the node has no delegate or it is not an instance of the passed
type, then None will be returned. If 'doraise' is True, then an
bascenev1.DelegateNotFoundError will be raised instead.
"""
return None
[docs]
def getname(self) -> str:
"""Return the name assigned to a Node; used mainly for debugging"""
# This is a dummy stub; the actual implementation is native code.
return str()
[docs]
def getnodetype(self) -> str:
"""Return the internal type of node referenced by this object as a string.
(Note this is different from the Python type which is always
:class:`bascenev1.Node`)
"""
# This is a dummy stub; the actual implementation is native code.
return str()
[docs]
def handlemessage(self, *args: Any) -> None:
"""General message handling; can be passed any message object.
All standard message objects are forwarded along to the node's
delegate for handling (generally the :class:`bascenev1.Actor` that
made the node).
Nodes also support a second form of message; 'node-messages'.
These consist of a string type-name as a first argument along with
the args specific to that type name as additional arguments.
Node-messages communicate directly with the low-level node
layer and are delivered simultaneously on all game clients, acting
as an alternative to setting node attributes.
"""
# This is a dummy stub; the actual implementation is native code.
return None
[docs]
class Quat(Sequence[float]):
"""A quaternion representing a rotation in 3d space.
These can be created the following ways (checked in this order):
- With no args, the identity (no-op) rotation is created.
- With a four-member sequence arg, sequence values are copied.
- Otherwise assumes individual w/x/y/z args (positional or keywords).
Quats are immutable, and are accepted anywhere a four-float
sequence is, so one can be assigned directly to node attrs such as
:attr:`bascenev1.Node.rotate`.
Note that most rotations are more easily built using
:meth:`~bascenev1.Quat.from_angles()` than by passing raw values
here.
"""
#: The quaternion's real component.
w: float
#: The quaternion's X component.
x: float
#: The quaternion's Y component.
y: float
#: The quaternion's Z component.
z: float
# pylint: disable=function-redefined
@overload
def __init__(self) -> None:
pass
@overload
def __init__(self, values: Sequence[float]):
pass
@overload
def __init__(self, w: float, x: float, y: float, z: float):
pass
def __init__(self, *args: Any, **kwds: Any):
pass
def __mul__(self, other: Quat) -> Quat:
return self
# (for index access)
@override
def __getitem__(self, typeargs: Any) -> Any:
return 0.0
@override
def __len__(self) -> int:
return 4
# (for iterator access)
@override
def __iter__(self) -> Any:
return self
def __next__(self) -> float:
return 0.0
[docs]
@classmethod
def from_angles(
cls, heading: float = 0.0, pitch: float = 0.0, roll: float = 0.0
) -> Quat:
"""Create a rotation from Euler angles, in degrees.
Heading is a rotation about the up (y) axis, pitch about the
sideways (x) axis, and roll about the forward (z) axis. They are
applied in that order, each about the axes left by the previous
one, so pitch tips an object relative to wherever its heading
left it facing.
Signs follow the usual aircraft convention: positive heading
turns right, positive pitch aims up, and positive roll banks
right.
"""
# This is a dummy stub; the actual implementation is native code.
return Quat()
[docs]
@classmethod
def from_direction(
cls, direction: Sequence[float], up: Sequence[float] = (0.0, 1.0, 0.0)
) -> Quat:
"""Create a rotation aiming forward (+z) along a direction.
The up vector is only a hint for which way to roll about that
direction; it gets squared up against it rather than being
followed exactly, so passing a rough one is fine. Aiming straight
along up leaves the roll undefined, in which case an arbitrary
one is picked rather than failing.
"""
# This is a dummy stub; the actual implementation is native code.
return Quat()
[docs]
def inverse(self) -> Quat:
"""Return the rotation undoing this one."""
# This is a dummy stub; the actual implementation is native code.
return Quat()
[docs]
def normalized(self) -> Quat:
"""Return a unit-length version of this rotation.
Composing many rotations together can accumulate enough error to
visibly skew things; this cleans that up.
"""
# This is a dummy stub; the actual implementation is native code.
return Quat()
[docs]
@classmethod
def slerp(cls, from_quat: Quat, to_quat: Quat, amount: float) -> Quat:
"""Interpolate between two rotations along the shortest arc.
An amount of 0 returns the first rotation and 1 the second, with
values between sweeping smoothly from one to the other at a
constant rate. Note that interpolating a rotation's individual
values (as :func:`bascenev1.animate_array()` would) does not do
this correctly, so prefer this call when animating rotations.
"""
# This is a dummy stub; the actual implementation is native code.
return Quat()
class SceneViewer:
"""A self-contained scene drawn to a texture, for showing in ui.
The scene is this machine's alone and wholly separate from any
game going on: it has its own nodes, look, camera, and clock,
and makes no sound. Build what should be in it by creating
nodes, materials, and so on under its :attr:`context`, and show
it by handing its :attr:`source` to a viewer widget (or by
drawing its :attr:`texture` some other way). It runs only while
its picture is being drawn somewhere and stands still otherwise.
Size is in pixels. A viewer widget sets it to the size it shows
the picture at, so what is passed here matters only until then
(or when drawing the texture some other way).
The viewer lives as long as this object does.
:meta private:
"""
def __init__(self, width: int, height: int) -> None:
pass
@property
def context(self) -> bascenev1.ContextRef:
"""The context of our scene. Things created with this as the
current context are created in our scene.
"""
raise NotImplementedError()
@property
def source(self) -> bauiv1.ViewerSource:
"""Us as something a viewer widget can show. It holds no claim
on us; a widget showing it once we are gone shows nothing.
"""
raise NotImplementedError()
@property
def texture(self) -> bauiv1.Texture:
"""The texture our scene is drawn to. Use it like any other;
on an image widget, for instance.
"""
raise NotImplementedError()
def set_camera(
self,
position: Sequence[float],
target: Sequence[float],
field_of_view: float = 30.0,
near_clip: float = 1.0,
far_clip: float = 100.0,
min_horizontal_field_of_view: float = 0.0,
) -> None:
"""Set where the scene is seen from and what is looked at.
Field of view is vertical, in degrees, so what is looked at
takes up the same share of the picture's height whatever
shape the picture is. A picture narrow enough to see less
across than min_horizontal_field_of_view (if one is given)
sees that much across and more up and down instead, so that
what is looked at gets smaller rather than cut off at the
sides.
Nothing nearer than near_clip or farther than far_clip gets
drawn; keep the span between them no wider than the scene
needs.
"""
# This is a dummy stub; the actual implementation is native code.
return None
def set_camera_shake(
self,
strength: float,
stiffness: float = 30.0,
damping: float = 2.0,
poke_interval_min: float = 0.5,
poke_interval_max: float = 1.0,
) -> None:
"""Give the camera a hand-held shake.
The camera stays where it is, but its aim wobbles left/right
and up/down on a damped spring, kicked in a random direction
every so often (a random time between the two poke intervals,
in seconds, apart). Strength is the size of a kick in degrees
per second of spin; 0 turns shake off. Stiffness and damping
shape the spring: stiffer wobbles faster, more damping settles
sooner. Still while camera shake is disabled.
"""
# This is a dummy stub; the actual implementation is native code.
return None
def set_camera_tilt_orbit(self, amount: float) -> None:
"""Swing the camera around its target as the device turns.
On devices with a gyro, turning the device turns the view of
what the camera looks at with it, the camera keeping its
distance and aim. Amount scales the turn: 1.0 turns the camera
as far as the device turned, 0.0 (the default) not at all. The
turn eases back to center over a couple of seconds once the
device holds still. Nothing happens while camera gyro is
disabled.
"""
# This is a dummy stub; the actual implementation is native code.
return None
def set_depth_of_field(
self,
focus: tuple[float, float] | None,
blur: tuple[float, float] | None = None,
) -> None:
"""Set what of the scene is in focus.
Both are pairs of distances out from the camera along the way
it is looking, nearer one first. Everything between the two
focus distances is sharp; from there things get blurrier out
to the blur distances (which lie outside the focus ones),
past which they are as blurry as things get. Pass None for
focus to have everything in focus, which is how viewers
start out.
This shows only where graphics quality is high or better;
below that everything is sharp regardless.
"""
# This is a dummy stub; the actual implementation is native code.
return None
def set_size(self, width: int, height: int) -> None:
"""Set the size of our texture in pixels."""
# This is a dummy stub; the actual implementation is native code.
return None
def set_sound(
self, enabled: bool, volume: float = 1.0, pan_scale: float = 1.0
) -> None:
"""Let the scene make sound (viewers start out silent).
Sounds are heard as the viewer's camera would hear them, not
the game's: placed relative to it (its steady aim; shake is
left out), their gain scaled by volume, and how far to the
sides they sit scaled by pan_scale (more pans them wider).
"""
# This is a dummy stub; the actual implementation is native code.
return None
def shutdown(self) -> None:
"""Take the scene down for good.
Everything in it is destroyed and most calls on this object
raise from here on. Happens by itself when this object goes
away; call it to not depend on when that is.
"""
# This is a dummy stub; the actual implementation is native code.
return None
class SessionData:
"""Internal; holds native data for the session.
:meta private:
"""
def context(self) -> bascenev1.ContextRef:
"""Return a context-ref pointing to the session."""
# This is a dummy stub; the actual implementation is native code.
import bascenev1 # pylint: disable=cyclic-import
return bascenev1.ContextRef()
def exists(self) -> bool:
"""Returns whether the SessionData still exists.
Most functionality will fail on a nonexistent instance.
"""
# This is a dummy stub; the actual implementation is native code.
return bool()
[docs]
class SessionPlayer:
"""A reference to a player in a :class:`~bascenev1.Session`.
These are created and managed internally and provided to your
:class:`~bascenev1.Session`/:class:`~bascenev1.Activity`
instances. Be aware that, like :class:`~bascenev1.Node` objects,
:class:`~bascenev1.SessionPlayer` objects are effectively 'weak'
references under-the-hood; a player can leave the game at any point.
For this reason, you should make judicious use of the
:meth:`bascenev1.SessionPlayer.exists()` method (or boolean operator) to
ensure that a :class:`SessionPlayer` is still present if retaining
references to one for any length of time.
"""
#: The unique numeric id of the player.
#:
#: Note that you can also use the boolean operator for this same
#: functionality, so a statement such as ``if player:`` will do
#: the right thing both for :class:`~bascenev1.SessionPlayer`
#: objects as well as values of ``None``.
id: int
#: This bool value will be True once the player has completed
#: any lobby character/team selection.
in_game: bool
#: The session-team this session-player is on. If the player is
#: still in its lobby selecting a team/etc. then a
#: :class:`~bascenev1.SessionTeamNotFoundError` will be raised.
sessionteam: bascenev1.SessionTeam
#: The input device associated with the player.
inputdevice: bascenev1.InputDevice
#: The base color for this player.
#: In team games this will match the team's
#: color.
color: Sequence[float]
#: A secondary color for this player.
#: This is used for minor highlights and accents
#: to allow a player to stand apart from his teammates
#: who may all share the same team (primary) color.
highlight: Sequence[float]
#: The character this player has selected in their profile.
#: For a player on a cloud profile this is the legacy standin
#: appearance; see cloud_spaz_def.
character: str
#: The cloud-composed look for the cloud profile this player
#: picked, or None when they are on a legacy profile or a
#: random look. Sites that spawn the player prefer this when
#: present. Made in the current context's scene (scene
#: objects never cross scenes), so read it in the context it
#: will be used in.
cloud_spaz_def: bascenev1.SpazDef | None
#: The current game-specific instance for this player.
activityplayer: bascenev1.Player | None
def __bool__(self) -> bool:
"""Support for bool evaluation."""
return bool(True) # Slight obfuscation.
[docs]
def exists(self) -> bool:
"""Return whether the underlying player is still in the game."""
# This is a dummy stub; the actual implementation is native code.
return bool()
[docs]
def get_account_id(self) -> str | None:
"""Return the account id this player is signed in under, or None if
not available. For players connected via protocol < 36 this
will be a V1 account id; for protocol >= 36 it will be a V2
account id. Note that this may require an active internet
connection (especially for network-connected players) and may
return None for a short while after a player initially joins
(while verification occurs).
"""
# This is a dummy stub; the actual implementation is native code.
return ''
[docs]
def get_icon(self) -> dict[str, Any]:
"""Return the character's legacy icon (images, colors, etc contained
in a dict).
Prefer :meth:`get_icon_depiction` where available; this is the
fallback for players without one. For a player on a cloud
profile it gives a standin icon in the profile's colors.
"""
# This is a dummy stub; the actual implementation is native code.
return {'foo': 'bar'}
[docs]
def get_icon_depiction(self) -> bascenev1.Depiction | None:
"""Return the player's icon as a depiction, if they have one.
Players on cloud profiles have one (the icon composed with
their profile); anyone else (legacy profiles, random looks,
bots) gets None and should be shown via :meth:`get_icon`. Show it
with a ``depictiondisplay`` node or anything else accepting a
:class:`~bascenev1.Depiction` (the
:class:`~bascenev1lib.actor.image.Image` actor,
:func:`~bascenev1.broadcastmessage` images). The usual pattern is
``player.get_icon_depiction() or player.get_icon()``.
The depiction is made in the current context's scene (scene
objects never cross scenes), so ask in the context it will be
shown in rather than holding one across activities.
"""
# This is a dummy stub; the actual implementation is native code.
return None
def get_icon_depiction_json(self) -> str | None:
"""Return the json :meth:`get_icon_depiction` builds from, if any.
For keeping a player's icon somewhere that outlives scenes (a
stats record, say).
:meta private:
"""
# This is a dummy stub; the actual implementation is native code.
return ''
def get_icon_info(self) -> dict[str, Any]:
"""(internal)
:meta private:
"""
# This is a dummy stub; the actual implementation is native code.
return {'foo': 'bar'}
[docs]
def get_name_depiction(self) -> bascenev1.Depiction | None:
"""Return the player's name as a depiction, if they have one.
This is the name as it shows on its own (an account's capsule, a
global profile's icon, or plain text), for places such as score
screens; players who joined through the lobby have one. It
carries the player's color (their team's in team games). Names
worked into other text should stay :meth:`getname`. Show it with
a ``depictiondisplay`` node or the
:class:`~bascenev1lib.actor.text.Text` actor. The usual pattern is
``player.get_name_depiction() or player.getname(full=True)``.
The depiction is made in the current context's scene (scene
objects never cross scenes), so ask in the context it will be
shown in rather than holding one across activities.
"""
# This is a dummy stub; the actual implementation is native code.
return None
def get_name_depiction_json(self) -> str | None:
"""Return the json :meth:`get_name_depiction` builds from, if any.
For keeping a player's name somewhere that outlives scenes (a
stats record, say).
:meta private:
"""
# This is a dummy stub; the actual implementation is native code.
return ''
[docs]
@deprecated(
'Use get_account_id instead. This method will be removed when api 9 support ends.'
)
def get_v1_account_id(self) -> str | None:
""".. deprecated::
Use :meth:`get_account_id` instead. This method will be
removed when api 9 support ends.
Return the account id this player is signed in under, if it can
be determined with relative certainty. Returns None otherwise.
"""
# This is a dummy stub; the actual implementation is native code.
return ''
[docs]
def getname(self, full: bool = False, icon: bool = True) -> str:
"""Returns the player's name. If ``icon`` is True, the long version of the
name may include an icon.
"""
# This is a dummy stub; the actual implementation is native code.
return str()
[docs]
def remove_from_game(self) -> None:
"""Removes the player from the game."""
# This is a dummy stub; the actual implementation is native code.
return None
[docs]
def send_feedback(self, *, event: str = 'impact_received') -> None:
"""Request physical feedback (controller rumble, device vibration) for
whoever is controlling this player.
``event`` says what happened, not what it should feel like; each
platform renders it however it does that best. Valid values are
'join', 'collect', 'grab', 'impact_dealt', 'impact_received' and
'death'. Note a device may render nothing at all for an event its
hardware cannot represent well, so don't rely on any particular one
always being felt.
Does nothing if the player has already left the game.
"""
# This is a dummy stub; the actual implementation is native code.
return None
def set_icon_info(
self,
texture: str,
tint_texture: str,
tint_color: Sequence[float],
tint2_color: Sequence[float],
tint3_color: Sequence[float] | None = None,
) -> None:
"""(internal)
:meta private:
"""
# This is a dummy stub; the actual implementation is native code.
return None
def setactivity(self, activity: bascenev1.Activity | None) -> None:
"""(internal)
:meta private:
"""
# This is a dummy stub; the actual implementation is native code.
return None
[docs]
def setdata(
self,
team: bascenev1.SessionTeam,
character: str,
color: Sequence[float],
highlight: Sequence[float],
cloud_spaz_json: str | None = None,
cloud_icon_json: str | None = None,
name_depiction_json: str | None = None,
) -> None:
"""(internal)"""
# This is a dummy stub; the actual implementation is native code.
return None
[docs]
def setname(
self, name: str, full_name: str | None = None, real: bool = True
) -> None:
"""Set the player's name to the provided string.
A number will automatically be appended if the name is not unique from
other players.
"""
# This is a dummy stub; the actual implementation is native code.
return None
def setnode(self, node: bascenev1.Node | None) -> None:
"""(internal)
:meta private:
"""
# This is a dummy stub; the actual implementation is native code.
return None
[docs]
class Sound:
"""A reference to a sound.
Use :meth:`bascenev1.getsound()` to instantiate one.
"""
[docs]
def play(
self,
volume: float = 1.0,
position: Sequence[float] | None = None,
host_only: bool = False,
play_group: str | None = None,
play_group_cap: int | None = None,
priority: bascenev1.SoundPriority | None = None,
) -> None:
"""Play the sound a single time.
If position is not provided, the sound will be at a constant volume
everywhere. Position should be a float tuple of size 3.
Only so many sounds can play at once, and the last three arguments
bear on which ones do when there are more than that. Sounds
belong to play groups; by default a sound's group comes from its
name, with numbered variations of a sound ('explosion01',
'explosion02') sharing one. Only a few sounds of a group play at
once, a new one cutting off the group's oldest. Pass
``play_group`` to count this play toward a group of your choosing
and ``play_group_cap`` to change how many of that group may play
at once (1 means each play cuts off the last). ``priority``
overrides the sound's own; see
:class:`~bascenev1.SoundPriority`.
"""
# This is a dummy stub; the actual implementation is native code.
return None
[docs]
class SpazDef:
"""A spaz definition: how a spaz node looks, sounds, and is
proportioned.
Built from a json spaz definition (a character's spaz part, as
delivered by the master server for a player's verified profile
or bundled for the builtin characters; see
:func:`bascenev1.split_character`) and assigned to a spaz node's
``spaz_def`` attr. The definition is opaque here; the node draws,
voices, and proportions itself from it, wearing a standard-spaz
standin until any media it references is available locally.
Lifetime works like :class:`Material`: the definition lives as
long as something references it (this object or a node attr)
and leaves the session automatically once nothing does.
Must be created in a host activity or host session context, and
can only be assigned to nodes of that same scene (scene objects
never cross scenes). A player's cloud look is made per scene for
you: read ``SessionPlayer.cloud_spaz_def`` in the context it
will be used in.
"""
def __init__(self, json: str) -> None:
pass
@property
def color(self) -> tuple[float, float, float] | None:
"""The definition's own primary color, or None if it carries none
(the node then takes its color attr). What a lobby offers as
the player's color when they pick this look; game modes may
still override per player.
"""
raise NotImplementedError()
@property
def highlight(self) -> tuple[float, float, float] | None:
"""The definition's own highlight color, or None if it carries
none.
"""
raise NotImplementedError()
@property
def highlight2(self) -> tuple[float, float, float] | None:
"""The definition's own second highlight color (its color mask's
blue channel; white when unset), or None if it carries no
colors.
"""
raise NotImplementedError()
[docs]
class Texture:
"""A reference to a texture.
Use :meth:`bascenev1.gettexture()` to instantiate one.
"""
pass
[docs]
class Timer:
"""Timers are used to run code at later points in time.
This class encapsulates a scene-time timer in the current
bascenev1.Context. The underlying timer will be destroyed when either
this object is no longer referenced or when its Context (Activity,
etc.) dies. If you do not want to worry about keeping a reference to
your timer around,
you should use the bs.timer() function instead.
Scene time maps to local simulation time in bascenev1.Activity or
bascenev1.Session Contexts. This means that it may progress slower
in slow-motion play modes, stop when the game is paused, etc.
Args:
time:
Length of time (in seconds by default) that the timer will wait
before firing. Note that the actual delay experienced may vary
depending on the timetype. (see below)
call:
A callable Python object. Note that the timer will retain a
strong reference to the callable for as long as it exists, so you
may want to look into concepts such as :class:`~babase.WeakCall`
if that is not desired.
repeat:
If True, the timer will fire repeatedly, with each successive
firing having the same delay as the first.
Example: Use a Timer object to print repeatedly for a few seconds::
import bascenev1 as bs
def say_it():
bs.screenmessage('BADGER!')
def stop_saying_it():
global g_timer
g_timer = None
bs.screenmessage('MUSHROOM MUSHROOM!')
# Create our timer; it will run as long as we hold its ref.
g_timer = bs.Timer(0.3, say_it, repeat=True)
# Now fire off a one-shot timer to kill the ref.
bs.timer(3.89, stop_saying_it)
"""
def __init__(
self, time: float, call: Callable[[], Any], repeat: bool = False
) -> None:
pass
def animcurve(
node: bascenev1.Node,
attr: str,
globals_node: bascenev1.Node,
times: Sequence[int],
values: Sequence[float],
offset: int,
loop: bool,
name: str,
) -> bascenev1.Node:
"""(internal)
Create an animcurve node driving attr on node (what bascenev1.animate
does): owned by node, keyed by times (ms) and values, offset by
offset (scene ms), driven by globals_node's 'time'. Under protocol
44+ the whole thing reaches the stream as one command.
"""
# This is a dummy stub; the actual implementation is native code.
import bascenev1 # pylint: disable=cyclic-import
return bascenev1.Node()
def apcollisionmeshget(apvernum: int, name: str) -> bascenev1.CollisionMesh:
"""Load a collision-mesh from an asset-package (internal).
Do not call this directly; asset-package assets should be accessed
through their package's generated Python wrapper module, which routes
through this call. Requires a fully-qualified '<apvernum>:<path>'
asset name.
:meta private:
"""
# This is a dummy stub; the actual implementation is native code.
import bascenev1 # pylint: disable=cyclic-import
return bascenev1.CollisionMesh()
def apmeshget(apvernum: int, name: str) -> bascenev1.Mesh:
"""Load a mesh from an asset-package (internal).
Do not call this directly; asset-package assets should be accessed
through their package's generated Python wrapper module, which routes
through this call. Requires a fully-qualified '<apvernum>:<path>'
asset name.
:meta private:
"""
# This is a dummy stub; the actual implementation is native code.
import bascenev1 # pylint: disable=cyclic-import
return bascenev1.Mesh()
def apsoundget(apvernum: int, name: str) -> bascenev1.Sound:
"""Load a sound from an asset-package (internal).
Do not call this directly; asset-package assets should be accessed
through their package's generated Python wrapper module, which routes
through this call. Requires a fully-qualified '<apvernum>:<path>'
asset name.
:meta private:
"""
# This is a dummy stub; the actual implementation is native code.
import bascenev1 # pylint: disable=cyclic-import
return bascenev1.Sound()
def aptextureget(apvernum: int, name: str) -> bascenev1.Texture:
"""Load a texture from an asset-package (internal).
Do not call this directly; asset-package assets should be accessed
through their package's generated Python wrapper module, which routes
through this call. Requires a fully-qualified '<apvernum>:<path>'
asset name.
:meta private:
"""
# This is a dummy stub; the actual implementation is native code.
import bascenev1 # pylint: disable=cyclic-import
return bascenev1.Texture()
[docs]
def basetime() -> bascenev1.BaseTime:
"""Return the base-time in seconds for the current scene-v1 context.
Base-time is a time value that progresses at a constant rate for a scene,
even when the scene is sped up, slowed down, or paused. It may, however,
speed up or slow down due to replay speed adjustments or may slow down
if the cpu is overloaded.
Note that the value returned here is simply a float; it just has a
unique type in the type-checker's eyes to help prevent it from being
accidentally used with time functionality expecting other time types.
"""
# This is a dummy stub; the actual implementation is native code.
import bascenev1 # pylint: disable=cyclic-import
return bascenev1.BaseTime(0.0)
[docs]
def basetimer(
time: float, call: Callable[[], Any], repeat: bool = False
) -> None:
"""Schedule a call to run at a later point in scene base-time.
Base-time is a value that progresses at a constant rate for a scene,
even when the scene is sped up, slowed down, or paused. It may,
however, speed up or slow down due to replay speed adjustments or may
slow down if the cpu is overloaded.
This function adds a timer to the current scene context.
This timer cannot be canceled or modified once created. If you
require the ability to do so, use the bascenev1.BaseTimer class
instead.
Args:
time:
Length of time in seconds that the timer will wait before firing.
call:
A callable Python object. Remember that the timer will retain a
strong reference to the callable for the duration of the timer, so
you may want to look into concepts such as :class:`~babase.WeakCall`
if that is not desired.
repeat:
If True, the timer will fire repeatedly, with each successive
firing having the same delay as the first.
Example: Print some stuff through time::
import bascenev1 as bs
bs.screenmessage('hello from now!')
bs.basetimer(1.0, bs.Call(bs.screenmessage,
'hello from the future!'))
bs.basetimer(2.0, bs.Call(bs.screenmessage,
'hello from the future 2!'))
"""
# This is a dummy stub; the actual implementation is native code.
return None
[docs]
def broadcastmessage(
message: str | babase.Lstr | babase.LangStr,
color: Sequence[float] | None = None,
top: bool = False,
image: dict[str, Any] | bascenev1.Depiction | None = None,
log: bool = False,
clients: Sequence[int] | None = None,
transient: bool = False,
) -> None:
"""Broadcast a screen-message to clients in the current session.
If 'top' is True, the message will go to the top message area.
For 'top' messages, 'image' must be a dict containing 'texture'
and 'tint_texture' textures and 'tint_color' and 'tint2_color'
colors and optionally a 'tint3_color', or a bascenev1.Depiction
(a player's get_icon_depiction(), say). This defines an icon to
display alongside the message.
If 'log' is True, the message will also be submitted to the log.
'clients' can be a list of client-ids the message should be sent
to, or None to specify that everyone should receive it.
If 'transient' is True, the message will not be included in the
game-stream and thus will not show up when viewing replays.
Currently the 'clients' option only works for transient messages.
"""
# This is a dummy stub; the actual implementation is native code.
return None
[docs]
def camerashake(intensity: float = 1.0) -> None:
"""Shake the camera.
Note that some cameras and/or platforms (such as VR) may not display
camera-shake, so do not rely on this always being visible to the
player as a gameplay cue.
"""
# This is a dummy stub; the actual implementation is native code.
return None
def capture_game_controller_input(call: Callable[[dict], None]) -> None:
"""Add a callable to be called for subsequent game controller events.
The method is passed a dict containing info about the event.
:meta private:
"""
# This is a dummy stub; the actual implementation is native code.
return None
def capture_keyboard_input(call: Callable[[dict], None]) -> None:
"""Add a callable to be called for subsequent keyboard-game-pad events.
The method is passed a dict containing info about the event.
:meta private:
"""
# This is a dummy stub; the actual implementation is native code.
return None
[docs]
def chatmessage(
message: str | babase.Lstr | babase.LangStr,
clients: Sequence[int] | None = None,
sender_override: str | None = None,
) -> None:
"""(internal)"""
# This is a dummy stub; the actual implementation is native code.
return None
def clear_scene_asset_set_native() -> None:
"""(internal) Drop any app-mode-supplied scene asset set.
Called by scene_v1's app-subsystem reset() at app-mode switches.
"""
# This is a dummy stub; the actual implementation is native code.
return None
[docs]
def client_info_query_response(token: str, response: Any) -> None:
"""(internal)"""
# This is a dummy stub; the actual implementation is native code.
return None
def connect_to_party(
address: str,
port: int | None = None,
print_progress: bool = True,
password: str | None = None,
prepped: bool = False,
) -> None:
"""(internal)"""
# This is a dummy stub; the actual implementation is native code.
return None
[docs]
def disconnect_client(client_id: int, ban_time: int = 300) -> bool:
"""(internal)"""
# This is a dummy stub; the actual implementation is native code.
return bool()
[docs]
def disconnect_from_host() -> None:
"""(internal)"""
# This is a dummy stub; the actual implementation is native code.
return None
[docs]
def emitfx(
position: Sequence[float],
velocity: Sequence[float] | None = None,
count: int = 10,
scale: float = 1.0,
spread: float = 1.0,
chunk_type: str = 'rock',
emit_type: str = 'chunks',
tendril_type: str = 'smoke',
) -> None:
"""Emit particles, smoke, etc. into the fx sim layer.
The fx sim layer is a secondary dynamics simulation that runs in
the background and just looks pretty; it does not affect gameplay.
Note that the actual amount emitted may vary depending on graphics
settings, exiting element counts, or other factors.
"""
# This is a dummy stub; the actual implementation is native code.
return None
[docs]
def end_host_scanning() -> None:
"""(internal)"""
# This is a dummy stub; the actual implementation is native code.
return None
[docs]
def get_chat_messages() -> list[str]:
"""(internal)"""
# This is a dummy stub; the actual implementation is native code.
return ['blah', 'blah2']
[docs]
def get_client_ping(client_id: int) -> float:
"""Return the current ping (RTT in ms) for a connected client.
Returns -1.0 if client_id is invalid.
"""
# This is a dummy stub; the actual implementation is native code.
return float()
def get_client_public_device_uuid(client_id: int) -> str | None:
"""(internal)
Return a public device UUID for a client. If the client does not
exist or is running a version older than 1.6.10, returns None.
Public device UUID uniquely identifies the device the client is
using in a semi-permanent way. The UUID value will change
periodically with updates to the game or operating system.
"""
# This is a dummy stub; the actual implementation is native code.
return ''
def get_collision_info(*args: Any) -> Any:
"""Return collision related values
Returns a single collision value or tuple of values such as location,
depth, nodes involved, etc. Only call this in the handler of a
collision-triggered callback or message
"""
# This is a dummy stub; the actual implementation is native code.
return _uninferrable()
def get_configurable_game_controllers() -> list:
"""Returns a list of the currently connected gamepads that can be
configured.
:meta private:
"""
# This is a dummy stub; the actual implementation is native code.
return list()
[docs]
def get_connection_to_host_info() -> dict:
"""(internal)"""
# This is a dummy stub; the actual implementation is native code.
return dict()
[docs]
def get_connection_to_host_info_2() -> bascenev1.HostInfo | None:
"""Return info about the host we are currently connected to."""
# This is a dummy stub; the actual implementation is native code.
import bascenev1 # pylint: disable=cyclic-import
return bascenev1.HostInfo('dummyname', -1, 'dummy_addr', -1)
def get_foreground_host_activity() -> bascenev1.Activity | None:
""":meta private:
Returns the bascenev1.Activity currently in the foreground,
or None if there is none.
"""
# This is a dummy stub; the actual implementation is native code.
import bascenev1 # pylint: disable=cyclic-import
return bascenev1.Activity(settings={})
def get_foreground_host_session() -> bascenev1.Session | None:
""":meta private:
Return the bascenev1.Session currently being displayed, or None if there is
none.
"""
# This is a dummy stub; the actual implementation is native code.
import bascenev1 # pylint: disable=cyclic-import
return bascenev1.Session()
[docs]
def get_game_port() -> int:
"""(internal)
Return the port ballistica is hosting on.
"""
# This is a dummy stub; the actual implementation is native code.
return int()
def get_game_roster() -> list[dict[str, Any]]:
""":meta private:"""
# This is a dummy stub; the actual implementation is native code.
return [{'foo': 'bar'}]
def get_local_active_input_devices_count() -> int:
""":meta private:"""
# This is a dummy stub; the actual implementation is native code.
return int()
[docs]
def get_main_ui_input_device() -> bascenev1.InputDevice | None:
"""Return the input-device currently controlling the main ui, or
None if there is none.
"""
# This is a dummy stub; the actual implementation is native code.
return InputDevice()
def get_node_attr_tables() -> dict[str, list[tuple[str, str]]]:
"""Return every node type's attr table in wire-index order.
:meta private:
"""
# This is a dummy stub; the actual implementation is native code.
return {'foo': [('bar', 'baz')]}
[docs]
def get_public_party_enabled() -> bool:
"""(internal)"""
# This is a dummy stub; the actual implementation is native code.
return bool()
[docs]
def get_public_party_max_size() -> int:
"""(internal)"""
# This is a dummy stub; the actual implementation is native code.
return int()
def get_random_names() -> list:
""":meta private:
Returns the random names used by the game.
"""
# This is a dummy stub; the actual implementation is native code.
return list()
def get_replay_asset_packages(file_name: str) -> list[int] | None:
"""Read a replay file's asset-package requirements from its header
without starting playback (returns None for a missing/unreadable
file, or one naming packages by pre-numeric string ids; an empty
list for a replay predating package tables).
:meta private:
"""
# This is a dummy stub; the actual implementation is native code.
return [0]
def get_replay_speed_exponent() -> int:
""":meta private:
Returns current replay speed value. Actual displayed speed is pow(2,speed).
"""
# This is a dummy stub; the actual implementation is native code.
return int()
def get_spaz_def_count() -> int:
"""Return the number of live spaz definitions in the foreground host
session's stream, or -1 if not hosting.
:meta private:
"""
# This is a dummy stub; the actual implementation is native code.
return int()
# Show that our return type varies based on "doraise" value:
@overload
def getactivity(doraise: Literal[True] = True) -> bascenev1.Activity: ...
@overload
def getactivity(doraise: Literal[False]) -> bascenev1.Activity | None: ...
[docs]
def getactivity(doraise: bool = True) -> bascenev1.Activity | None:
"""Return the current bascenev1.Activity instance.
Note that this is based on context_ref; thus code run in a timer
generated in Activity 'foo' will properly return 'foo' here, even if
another Activity has since been created or is transitioning in.
If there is no current Activity, raises a babase.ActivityNotFoundError.
If doraise is False, None will be returned instead in that case.
"""
return None
[docs]
def getcollisionmesh(name: str) -> bascenev1.CollisionMesh:
"""Return a collision-mesh, loading it if necessary.
Collision-meshes are used in physics calculations for such things as
terrain.
Note that this function returns immediately even if the asset has yet
to be loaded. Loading will happen in the background or on-demand. To
avoid hitches, try to instantiate asset objects a bit earlier than
they are actually needed, giving them time to load gracefully
in the background.
"""
# This is a dummy stub; the actual implementation is native code.
import bascenev1 # pylint: disable=cyclic-import
return bascenev1.CollisionMesh()
[docs]
def getdata(name: str) -> bascenev1.Data:
"""Return a data, loading it if necessary.
Note that this function returns immediately even if the asset has yet
to be loaded. Loading will happen in the background or on-demand. To
avoid hitches, try to instantiate asset objects a bit earlier than
they are actually needed, giving them time to load gracefully
in the background.
"""
# This is a dummy stub; the actual implementation is native code.
import bascenev1 # pylint: disable=cyclic-import
return bascenev1.Data()
# Show that our return type varies based on "doraise" value:
@overload
def getinputdevice(
name: str, unique_id: str, doraise: Literal[True] = True
) -> bascenev1.InputDevice: ...
@overload
def getinputdevice(
name: str, unique_id: str, doraise: Literal[False]
) -> bascenev1.InputDevice | None: ...
def getinputdevice(name: str, unique_id: str, doraise: bool = True) -> Any:
"""Given a type name and a unique identifier, returns an InputDevice.
Throws an Exception if the input-device is not found, or returns None
if 'doraise' is False.
:meta private:
"""
return None
# Show that our return type varies based on "doraise" value:
@overload
def getlocaldisplay(
doraise: Literal[True] = True,
) -> bascenev1.LocalDisplay: ...
@overload
def getlocaldisplay(
doraise: Literal[False],
) -> bascenev1.LocalDisplay | None: ...
[docs]
def getlocaldisplay(doraise: bool = True) -> bascenev1.LocalDisplay | None:
"""Return the current bascenev1.LocalDisplay instance.
Like getactivity(), this is based on context_ref; code run in a
timer created within a local-display's context will return that
local-display here. If there is no current local-display, raises a
babase.NotFoundError. If doraise is False, None will be returned
instead in that case.
"""
return None
[docs]
def getmesh(name: str) -> bascenev1.Mesh:
"""Return a mesh, loading it if necessary.
Note that this function returns immediately even if the asset has yet
to be loaded. Loading will happen in the background or on-demand. To
avoid hitches, try to instantiate asset objects a bit earlier than
they are actually needed, giving them time to load gracefully
in the background.
"""
# This is a dummy stub; the actual implementation is native code.
import bascenev1 # pylint: disable=cyclic-import
return bascenev1.Mesh()
[docs]
def getnodes() -> list:
"""Return all nodes in the current scene context."""
# This is a dummy stub; the actual implementation is native code.
return list()
# Show that our return type varies based on "doraise" value:
@overload
def getsession(doraise: Literal[True] = True) -> bascenev1.Session: ...
@overload
def getsession(doraise: Literal[False]) -> bascenev1.Session | None: ...
[docs]
def getsession(doraise: bool = True) -> bascenev1.Session | None:
"""Return the session associated with the current context. If there is
none, a :class:`~bascenev1.SessionNotFoundError` is raised (unless
``doraise`` is False, in which case ``None`` is returned instead).
"""
return None
[docs]
def getsound(name: str) -> bascenev1.Sound:
"""Return a sound, loading it if necessary.
Note that this function returns immediately even if the asset has yet
to be loaded. Loading will happen in the background or on-demand. To
avoid hitches, try to instantiate asset objects a bit earlier than
they are actually needed, giving them time to load gracefully
in the background.
"""
# This is a dummy stub; the actual implementation is native code.
import bascenev1 # pylint: disable=cyclic-import
return bascenev1.Sound()
[docs]
def gettexture(name: str) -> bascenev1.Texture:
"""Return a texture, loading it if necessary.
Note that this function returns immediately even if the asset has yet
to be loaded. Loading will happen in the background or on-demand. To
avoid hitches, try to instantiate asset objects a bit earlier than
they are actually needed, giving them time to load gracefully
in the background.
"""
# This is a dummy stub; the actual implementation is native code.
import bascenev1 # pylint: disable=cyclic-import
return bascenev1.Texture()
def have_connected_clients() -> bool:
"""(internal)
:meta private:
"""
# This is a dummy stub; the actual implementation is native code.
return bool()
def have_touchscreen_input() -> bool:
"""Internal; Return whether or not a touch-screen input is present.
:meta private:
"""
# This is a dummy stub; the actual implementation is native code.
return bool()
def host_scan_cycle() -> list[dict[str, Any]]:
"""Run a lan-scan cycle and return results gathered so far.
Hosts answering only the old v1 query form have ``has_v2`` False
and carry defaults for the v2-only fields (``party_name``,
``party_size``, ``party_max_size``, ``auth_required``,
``build_number``, ``protocol_version``).
(internal)
:meta private:
"""
# This is a dummy stub; the actual implementation is native code.
return [{'foo': 'bar'}]
def host_ui_send_to_client(client_id: int, message: str) -> bool:
"""Send a serialized host-ui message to a connected client.
Returns False (and sends nothing) if there is no such client or
it is too old to understand host-ui messages.
:meta private:
"""
# This is a dummy stub; the actual implementation is native code.
return bool()
def host_ui_send_to_host(message: str) -> bool:
"""Send a serialized host-ui message to the host we are connected to.
Returns False (and sends nothing) if we're not connected or the
host is too old to understand host-ui messages.
:meta private:
"""
# This is a dummy stub; the actual implementation is native code.
return bool()
def is_in_replay() -> bool:
""":meta private:"""
# This is a dummy stub; the actual implementation is native code.
return bool()
def is_replay_paused() -> bool:
""":meta private:
Returns if Replay is paused or not.
"""
# This is a dummy stub; the actual implementation is native code.
return bool()
[docs]
def ls_objects() -> None:
"""Log debugging info about C++ level objects.
This call only functions in debug builds of the game.
It prints various info about the current object count, etc.
"""
# This is a dummy stub; the actual implementation is native code.
return None
def new_host_session(
sessiontype: type[bascenev1.Session], benchmark_type: str | None = None
) -> None:
""":meta private:"""
# This is a dummy stub; the actual implementation is native code.
return None
def new_replay_session(file_name: str) -> None:
""":meta private:"""
# This is a dummy stub; the actual implementation is native code.
return None
[docs]
def newactivity(
activity_type: type[bascenev1.Activity], settings: dict | None = None
) -> bascenev1.Activity:
"""Instantiates a bascenev1.Activity given a type object.
Activities require special setup and thus cannot be directly
instantiated; you must go through this function.
"""
# This is a dummy stub; the actual implementation is native code.
import bascenev1 # pylint: disable=cyclic-import
return bascenev1.Activity(settings={})
[docs]
def newnode(
type: str,
owner: bascenev1.Node | None = None,
attrs: dict | None = None,
name: str | None = None,
delegate: Any = None,
) -> bascenev1.Node:
"""Add a node of the given type to the game.
If a dict is provided for 'attributes', the node's initial attributes
will be set based on them.
'name', if provided, will be stored with the node purely for debugging
purposes. If no name is provided, an automatic one will be generated
such as 'terrain@foo.py:30'.
If 'delegate' is provided, Python messages sent to the node will go to
that object's handlemessage() method. Note that the delegate is stored
as a weak-ref, so the node itself will not keep the object alive.
if 'owner' is provided, the node will be automatically killed when that
object dies. 'owner' can be another node or a bascenev1.Actor
"""
# This is a dummy stub; the actual implementation is native code.
import bascenev1 # pylint: disable=cyclic-import
return bascenev1.Node()
def packet_compression_selftest() -> dict:
"""(internal)
Round-trip a sample packet through the active packet codec and
return {'codec', 'raw', 'compressed'}; raises if the round trip
fails. For checking a platform's zstd link at runtime.
"""
# This is a dummy stub; the actual implementation is native code.
return dict()
def pause_replay() -> None:
""":meta private:
Pauses replay.
"""
# This is a dummy stub; the actual implementation is native code.
return None
[docs]
def printnodes() -> None:
"""Print various info about existing nodes; useful for debugging."""
# This is a dummy stub; the actual implementation is native code.
return None
def protocol_version() -> int:
""":meta private:"""
# This is a dummy stub; the actual implementation is native code.
return int()
def register_activity(activity: bascenev1.Activity) -> bascenev1.ActivityData:
""":meta private:"""
# This is a dummy stub; the actual implementation is native code.
import bascenev1 # pylint: disable=cyclic-import
return bascenev1.ActivityData()
def register_session(session: bascenev1.Session) -> bascenev1.SessionData:
""":meta private:"""
# This is a dummy stub; the actual implementation is native code.
import bascenev1 # pylint: disable=cyclic-import
return bascenev1.SessionData()
def release_game_controller_input() -> None:
"""Resumes normal game controller event processing.
:meta private:
"""
# This is a dummy stub; the actual implementation is native code.
return None
def release_keyboard_input() -> None:
"""Resumes normal keyboard event processing.
:meta private:
"""
# This is a dummy stub; the actual implementation is native code.
return None
[docs]
def reload_hooks() -> None:
"""Reload functions and other objects held by the native layer.
Call this if you replace things in a hooks module to get the
native layer to see your changes.
"""
# This is a dummy stub; the actual implementation is native code.
return None
def reset_random_player_names() -> None:
""":meta private:"""
# This is a dummy stub; the actual implementation is native code.
return None
def resume_replay() -> None:
""":meta private:
Resumes replay.
"""
# This is a dummy stub; the actual implementation is native code.
return None
def seek_replay(delta: float) -> None:
""":meta private:
Rewind or fast-forward replay.
"""
# This is a dummy stub; the actual implementation is native code.
return None
[docs]
def set_authenticate_clients(enable: bool, *, optional: bool = False) -> None:
"""(internal)
With optional, auth is offered (while we're online) but not
required: joiners that can authenticate do, anyone else joins
unauthenticated. Affects connections made from then on.
"""
# This is a dummy stub; the actual implementation is native code.
return None
def set_debug_speed_exponent(speed: int) -> None:
""":meta private:
Sets the debug speed scale for the game. Actual speed is pow(2,speed).
"""
# This is a dummy stub; the actual implementation is native code.
return None
def set_host_password(password: str | None) -> None:
"""Set the password clients must provide to join us.
Pass None or an empty string for no password. Advertised (as a
required-flag only) in pre-join requirements-query responses.
(internal)
:meta private:
"""
# This is a dummy stub; the actual implementation is native code.
return None
def set_hosting_asset_packages(packages: Sequence[int]) -> None:
"""Set the asset-package-versions this app run hosts with.
This should be the launch metascan snapshot (the app's hosting
package universe; see asset-packages.md decision #36). Advertised
to LAN scanners in v2 host-query responses.
(internal)
:meta private:
"""
# This is a dummy stub; the actual implementation is native code.
return None
[docs]
def set_internal_music(
music: babase.SimpleSound | None,
volume: float = 1.0,
loop: bool = True,
fade_out: float = 0.0,
) -> None:
""":meta private:."""
# This is a dummy stub; the actual implementation is native code.
return None
def set_map_bounds(
bounds: tuple[float, float, float, float, float, float],
) -> None:
""":meta private:
Set map bounds. Generally nodes that go outside of this box are killed.
"""
# This is a dummy stub; the actual implementation is native code.
return None
[docs]
def set_master_server_source(source: int) -> None:
"""(internal)"""
# This is a dummy stub; the actual implementation is native code.
return None
def set_packet_compression_dict(data: bytes) -> None:
"""(internal)
Install the zstd dictionary used to compress scene game packets
(bacommon.packetzstddict). Called once at app start; connections
made before it stay on the legacy huffman.
"""
# This is a dummy stub; the actual implementation is native code.
return None
[docs]
def set_public_party_enabled(enabled: bool) -> None:
"""(internal)"""
# This is a dummy stub; the actual implementation is native code.
return None
[docs]
def set_public_party_max_size(max_size: int) -> None:
"""(internal)"""
# This is a dummy stub; the actual implementation is native code.
return None
[docs]
def set_public_party_name(name: str) -> None:
"""(internal)"""
# This is a dummy stub; the actual implementation is native code.
return None
[docs]
def set_public_party_public_address_ipv4(address: str | None) -> None:
"""(internal)"""
# This is a dummy stub; the actual implementation is native code.
return None
[docs]
def set_public_party_public_address_ipv6(address: str | None) -> None:
"""(internal)"""
# This is a dummy stub; the actual implementation is native code.
return None
[docs]
def set_public_party_queue_enabled(max_size: bool) -> None:
"""(internal)"""
# This is a dummy stub; the actual implementation is native code.
return None
[docs]
def set_public_party_stats_url(url: str | None) -> None:
"""(internal)"""
# This is a dummy stub; the actual implementation is native code.
return None
def set_replay_speed_exponent(speed: int) -> None:
""":meta private:
Set replay speed. Actual displayed speed is pow(2, speed).
"""
# This is a dummy stub; the actual implementation is native code.
return None
def set_scene_asset_set_native(
*args: bascenev1.TextureHandle
| bascenev1.MeshHandle
| bascenev1.SoundHandle,
) -> None:
"""(internal) Supply the assets the node layer draws itself with.
Do not call this directly -- bascenev1.set_scene_asset_set() is
the entry point. Args arrive positionally in spec order; both
sides are generated from
src/codegen/bascenev1codegen/scene_assets.py, so they cannot
drift.
"""
# This is a dummy stub; the actual implementation is native code.
return None
def set_touchscreen_editing(editing: bool) -> None:
""":meta private:"""
# This is a dummy stub; the actual implementation is native code.
return None
[docs]
def time() -> bascenev1.Time:
"""Return the current scene time in seconds.
Scene time maps to local simulation time in bascenev1.Activity or
bascenev1.Session Contexts. This means that it may progress slower
in slow-motion play modes, stop when the game is paused, etc.
Note that the value returned here is simply a float; it just has a
unique type in the type-checker's eyes to help prevent it from being
accidentally used with time functionality expecting other time types.
"""
# This is a dummy stub; the actual implementation is native code.
import bascenev1 # pylint: disable=cyclic-import
return bascenev1.Time(0.0)
[docs]
def timer(time: float, call: Callable[[], Any], repeat: bool = False) -> None:
"""Schedule a call to run at a later point in time.
This function adds a scene-time timer to the current
:class:`bascenev1.ContextRef`. This timer cannot be canceled or modified
once created. If you require the ability to do so, use the
:class:`bascenev1.Timer` class instead.
Scene time maps to local simulation time in :class:`bascenev1.Activity`
or :class:`bascenev1.Session` Contexts. This means that it may progress
slower in slow-motion play modes, stop when the game is paused, etc.
Args:
time:
Length of scene time in seconds that the timer will wait
before firing.
call:
A callable Python object. Note that the timer will retain a
strong reference to the callable for as long as it exists, so you
may want to look into concepts such as :class:`bascenev1.WeakCall`
if that is not desired.
repeat:
If True, the timer will fire repeatedly, with each successive
firing having the same delay as the first.
Examples
========
Print some stuff through time::
import bascenev1 as bs
bs.screenmessage('hello from now!')
bs.timer(1.0, bs.Call(bs.screenmessage, 'hello from the future!'))
bs.timer(2.0, bs.Call(bs.screenmessage, 'hello from the future 2!'))
"""
# This is a dummy stub; the actual implementation is native code.
return None
# Docs-generation hack; import some stuff that we likely only forward-declared
# in our actual source code so that docs tools can find it.
from typing import (Coroutine, Any, Literal, Callable,
Generator, Awaitable, Sequence, Self, TypeIs)
import asyncio
from concurrent.futures import Future
from pathlib import Path
from enum import Enum