https://github.com/benjamin-dobell/ge_tts
https://github.com/benjamin-dobell/ge_tts
Last synced: 7 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/benjamin-dobell/ge_tts
- Owner: Benjamin-Dobell
- License: mit
- Created: 2019-10-21T15:03:41.000Z (almost 6 years ago)
- Default Branch: master
- Last Pushed: 2024-08-09T05:54:51.000Z (about 1 year ago)
- Last Synced: 2024-08-09T06:53:54.042Z (about 1 year ago)
- Language: Lua
- Size: 264 KB
- Stars: 22
- Watchers: 7
- Forks: 5
- Open Issues: 0
-
Metadata Files:
- Readme: README.asciidoc
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
= Glass Echidna Tabletop Simulator Libraries
:toc:
ifndef::env-github[:icons: font]
ifdef::env-github[]
:tip-caption: :bulb:
:note-caption: :information_source:
:important-caption: :heavy_exclamation_mark:
:caution-caption: :fire:
:warning-caption: :warning:
endif::[]toc::[]
== License
Everything in this repository is permissively licensed under the MIT
license, please refer to the `LICENSE` file.== Discord
If you’d like to discuss ge_tts, you can do so on the
https://discord.gg/YwD22SM[TTS Community Discord].== Example project
For a quick overview of how to build a mod with ge_tts, please take a
look at the https://github.com/Benjamin-Dobell/ge_tts_demo[demo
project].== Luanalysis and Jetbrains IntelliJ IDEA
For development of your TTS mod we highly recommend using Jetbrains
IntelliJ IDEA with a
https://github.com/Benjamin-Dobell/IntelliJ-Luanalysis[Luanalysis] to
write your code, instead of (or rather in conjunction with) Atom and the
Atom TTS plugin.https://www.jetbrains.com/idea/download/[IntelliJ Community Edition] and
Luanalysis are both free, and offer significantly more advanced Lua
editing capabilities than Atom.Most importantly, we’ve included Luanalysis type definitions for our
APIs. This means that when you use our types, function and variable
names will auto-complete. Additionally, when using Luanalysis you’ll
want https://github.com/Benjamin-Dobell/tts-types[Tabletop Simulator
Luanalysis Types] which enable auto-completion _and_ type checking._However_, at present there is not yet a Tabletop Simulator plugin
available for Jetbrains IntelliJ IDEA. So you must still use Atom for
loading code out of, and saving code into Tabletop Simulator.== Requiring modules
ge_tts is split up into standard Lua modules. In order to use these
modules you must https://www.lua.org/pil/8.1.html[require] them.[NOTE]
====
e.g.[source,lua]
----
local TableUtils = require('ge_tts.TableUtils')log(TableUtils.merge({
a = 1
}, {
b = 2
}))
----
====The official Atom plugin has built-in support for `require`. Otherwise,
if your IDE doesn’t support it, you can use
https://github.com/Benjamin-Dobell/luabundler[luabundler] from command
line. However, this is an advanced solution, Atom is recommended for
pushing code to TTS.== API
To browse the precise APIs available, you should open up a module in
your IDE and refer to the inline documentation (comments). What follows
is a simply a quick overview of these modules.=== Base64
A package for encoding and decoding Base64 binary data.
=== Coroutine
Convenience functions for working with co-routines that are, for
example, to be executed every X frames, or every X seconds.e.g.
[source,lua]
----
Coroutine.start(function()
print("Immediately")Coroutine.yieldSeconds(1)
print("One second later")
Coroutine.yieldFrames(30)
print("30 frames later")
local object = CaspawnObject({type = "BlockRectangle"})Coroutine.yieldCondition(function() return not object.spawning end)
print("After the object finished spawning")
end)
----=== Debug
Simply utility to facilitate debugging within TTS.
==== `Debug.createGlobals(prefix = "")`
Registers all `require()`d ge_tts types as global variables so they can
easily used from TTS’ console.e.g. If you include `Debug.createGlobals()` at the bottom of your script
....
/execute
....=== DropZone
A `Zone` that acts as flexible, extensible and scriptable replacement
for TTS snap points. When an object is dropped in `DropZone` the object
will be smoothly animated into the center of the zone (and rotated
accordingly).`DropZone` also have an optional `occupantScale` which specifies how
dropped objects should be scaled (along the X-axis) when they’re dropped
in the DropZone, aspect ratio is always preserved. Automatic scaling can
be used to provide visual queues about important objects, or rather
objects placed in important locations/zones.To extend `DropZone`’s functionality you can ``sub-class'' `DropZone`
and override the `filterObject`, `onEnter`, `onLeave`, `onDrop` and
`onPickup` functions as desired.`DropZone` is itself a sub-class of `Zone`, so for an example of how you
can extend a ``class'' please refer to `DropZone.ttslua` (or
`HandZone.ttslua`).=== EventManager
TTS has several events which are called as global functions on a script.
It’s fairly common to have several objects or unrelated pieces of code
that are interested in these events.`EventManager` allows several pieces of code to subscribe to the one
event. If you have already written global event handler functions you
must move their definition _above_ any `require()` of ge_tts modules in
the same script, otherwise your exising handlers will interfere with
`EventManager`.=== Graph
A package with functions useful for working with node hierarchies
e.g. TTS UI (``XML'') tables.=== HandZone
A `Zone` that belongs to a player (owner) and corresponds with one of
their hands (most games just have the one hand). When instantiated
`HandZone` will automatically size itself to encompass the associated
TTS hand zone so that you can programatically track cards that are in
the players hand.Typically, to make use of this package you’d create your own
package/``class'' where you extend `HandZone` and override the
`onEnter`, `onLeave`, `onDrop` and `onPickup` functions as desired.`HandZone` is itself a sub-class of `Zone`, so for an example of how you
can extend a ``class'' please refer to `HandZone.ttslua` (or
`DropZone.ttslua`).=== Http
Http convenience module which wraps Tabletop Simulators WebRequest API.
The Http module will automatically encode/decode JSON, otherwise you can
provide a string and specify headers yourself.=== Instance
IMPORTANT: ge_tts does not presently support `Instance` being stored
in _nested_ containers i.e. Cards placed in a deck are fine. However,
ge_tts is _presently_ unable to track `Instance` referring to a card in
a deck _in a bag_._Please refer to
https://github.com/Benjamin-Dobell/ge_tts_demo[ge_tts_demo] for a
demonstration._Unlike TTS objects, which are destroyed when entering a container,
instances more closely resemble the concept of a real world game piece,
and are only destroyed if you delete the object in TTS.`Instance` also provides some convenience methods that help you interact
with TTS objects. For example, `reject()` knows how to return a TTS
object to wherever it previously came from; either its previous zone, or
if it has never been in a zone before, wherever it was picked up from.=== InstanceManager
WARNING: This is an _advanced_ feature, and makes implementing saving
and loading more difficult.`InstanceManager` exists for the sole purpose of improving save
performance.`InstanceManager` is beneficial if your mod has a lot of `Instance`
(typically 500+) or some of your `Instance` sub-classes are storing a
lot of data that changes infrequently. `InstanceManager` essentially
introduces a caching layer, that results in each instance’s `save()`
being called only when absolutely necessary, and most importantly,
smaller less frequent JSON encodes.[arabic]
. You _enable_ use of an `InstanceManager` with
`InstanceManager.set(yourInstanceManager)`.
+
[TIP]
====
You _don’t_ need to sub-class `InstanceManager`.
[source,lua]
----
InstanceManager.set(InstanceManager())
----
is perfectly acceptable.
====. Your main module’s `onSave` (`SaveManager.registerOnSave`) must call
`InstanceManager.save()` and `onLoad` (`SaveManager.registerOnLoad`)
must call `InstanceManager.load()`.. You must call `self.invalidateSavedState()` on an `Instance`, if you
know its saved state is dirty.. When saving an instance, call
`InstanceManager.saveInstanceState(instance)` and store the returned
instance GUID only. As opposed to calling `instanced.save()` and storing
the generated saved stated (which is what you’d do without the
`InstanceManager`).. When loading/recreating an instance, call
`InstanceManager.loadInstanceState(instanceGuid)` to obtain the saved
state of the `Instance`, which you’ll then provide to the `Instance`’s
constructor.When enabled `InstanceManager` will persist `Instance` saved state
(i.e. return value of `save()`) to the corresponding TTS object’s
`script_state`.=== Logger
A robust logging system with support for log levels and filtering.
=== PlayerDropZone
A `DropZone` that is associated with a particular TTS player,
specifically instances have an additional `getOwner()`.=== RemoteLogger
A `Logger` that rather than printing to TTS’ console, will HTTP `PUT` a
JSON object with `messages` (array of strings) to a URL that you provide
when instantiating the `RemoteLogger`.Using HTTP `PUT` instead of `POST` is pretty severe abuse of HTTP
semantics, however we don’t have a choice as TTS’ HTTP functionality is
severely lacking and cannot `POST` JSON.WARNING: The `Content-Type` of the request is `octet-stream` instead
of the correct type `application/json`. As mentioned, TTS’ HTTP client
is currently very limited and does not allow us to set headers.We don’t presently provide a corresponding server, but it’s pretty
trivial to create your own in Python, Ruby, Node.js etc.Remote logs could be useful for diagnosing issues your players are
running into, however personally I just use it in development as my logs
are kept even if TTS crashes, and it’s easy to copy and paste data from
my logs etc.=== SaveManager
SaveManager allows modules/files to independently maintain their own
saved state, without conflicting with other saved state from other
modules/files.=== TableUtils
Several convenience methods to be used in conjunction with tables.
WARNING: For both performance and semantic reasons, this module will
only operate on tables that are either _arrays_ or _hashes/maps_, but
not tables that are _both_ simultaneously. Behavior is undefined for
tables that contain a key for [1] _as well as_ non-consecutive integer,
or non-integer, keys.=== Vector2
2D vector implementation.
=== Vector3
3D vector implementation.
This was written before TTS had its own `Vector` class and is used
through-out this library. You may pass `Vector3` to any TTS method that
accepts a vector. However, it’s worth keeping in mind that our methods
return a `Vector3`, whilst TTS’s own methods return `Vector`.In general TTS’ `Vector` and our `Vector3` offer a similar set of
functionality, however you can call `Vector3` methods the same way you’d
call methods on any complex type in TTS API i.e. `vector1.add(vector2)`,
where as TTS’ `Vector` requres you to do `vector1:add(vector2)`.Additionally, all `Vector3` methods will happily accept a `Vector3`, a
`Vector`, a table with entries `x`, `y` and `z`, or a table with entries
`[1]`, `[2]` and `[3]` as arguments. Where as the TTS-provided `Vector`
is a bit more restrictive and will only accept arguments that are also
`Vector` e.g.[source,lua]
----
local v = Vector()
v:scale({1, 3, 1}) -- This will throw an errorlocal v3 = Vector3()
v3.scale({1, 3, 1}) -- This works fine, as does...
v3.scale(v)
v3.scale({x = 1, y = 3, z = 1})
----=== Zone
A wrapper around a TTS scripting trigger (`ScriptingTrigger`) that
tracks dropped and picked up objects. Objects that have been dropped in
the `Zone` are deemed to be occupying and can be retrieved with
`getOccupyingObjects()`.Typically, you’ll want to use a `DropZone`, `PlayerDropZone` or
`HandZone` rather than `Zone`. However, you may sub-class `Zone` if you
wish.