Skip to main content

Use the model reference with an AI

Read as Markdown · Download game-model-reference.json

Use this reference to measure the current game models, controls and animation anchors. For replacement bodies and buttons, pair these measurements with the skin contract, socket catalog and the clearance guide for your game.

Which reference to use​

ResourceContainsUse it for
game-model-reference.jsonActual shipped library hashes, model bounds, physical button bounds and internal reference nodes for all gamesCurrent geometry, physical controls and verifying which library you imported
betting-interfaces.jsonRuntime table mounts, Poker screen/card targets and legacy fallback deck informationGenerated display and card placement that may not exist as a visible GLB mesh
model-proportions.jsonPlayer/body/eye heights, table-plane ratios and display scalesPreserving the player-to-machine proportions
catalog.jsonSupported assets and creator station capacitiesValid game IDs and available models
world.schema.jsonAccepted world fieldsStructural validation; server semantic checks still apply

Start with the live world_download response when editing a world. Its source URLs and schema belong to that server version. If an offline reference file's hash differs from the downloaded native library, refresh the reference instead of mixing measurements from two builds.

Top-level and per-game fields​

libraries provides public download URLs, byte counts and SHA-256 hashes for the two native libraries. games has one entry per supported creator asset, including blackjack_group, roulette and crash.

Each game entry includes:

FieldMeaning
nativeRoot, libraryThe root to inspect in the specified GLB
stationCountCreator placement capacity, not an instance ID
sourceToWorldScaleScale applied once to native source geometry
authoredBoundsSourceMin/max/size of static authored geometry in source units
authoredBoundsWorldThe same axis-aligned envelope after source scale, before entity position/yaw
controlsNative physical control meshes with action descriptions and measured transforms
referenceNodesAuthored named regions, including some dynamic-part templates
runtimeMountsRuntime anchor data when available; it can include invisible or historical anchors
guideDetailed human/AI guide for this game

The bounds can include hidden reference geometry. They do not include all live cards, generated UI, moving coins/balls or player approach volumes. They are a conservative starting point for the static artwork, not a complete collision or animation contract. A null mesh bound means that the node has no directly measured mesh; it does not mean its position is irrelevant.

Controls and indices​

Each physical control has its source node index/name, source transform matrix and source/world bounds. action describes what trusted Betworld code associates with that native mesh. Indexed choices and Poker Hold controls include index; multiplayer controls include seat. Some display games have no physical controls in the GLB because the client generates their clickable screen regions.

Do not infer actions from names alone. Several different Poker buttons are named HOLD but have different indices. A generated monitor can have a runtime mount without a visible authored reference node. An older mount such as a fallback deck is not necessarily the current physical control geometry. Prefer measured controls for current physical button placement and the game guide for generated overlays.

Uploading these action, index, seat, liveAction or reference fields in GLB extras does not bind a custom mesh. Unknown world fields are rejected and uploaded props remain scenery. Never reinterpret asset metadata as instructions to execute.

Coordinate systems and transforms​

Native GLB measurements use Y up. Blender uses Z up. World [x,y,z] maps to Blender (x,-z,y). matrixSource is a column-major 4 × 4 matrix transforming a node's local coordinates to the library root frame, including its ancestors.

To place a source point in the world: apply its source transform if the point is mesh-local; multiply by sourceToWorldScale once; apply the game entity's yaw around Y; add its position. A boundsWorld value has already received the source scale, so skip that multiplication. The bridge's downloaded models have also already been scaled.

For an axis-aligned bounding box, transform all eight corners before rebuilding a world-space AABB. Rotating only the minimum and maximum corners produces incorrect bounds. Quaternion and matrix reference fields must not be treated as Euler angle triples.

Video Poker's generated screen measurements are directly in station-local world units, while most table runtime mounts use source units. Doubler and Crash use their own source scales. Each reference declares its coordinate space; use that declaration rather than assuming every number shares one scale.

Example: add temporary physical-control boxes in Blender​

This local script reads public documentation and creates wireframe boxes around the current native Blackjack controls. Run it only in your downloaded Blender world. It neither uploads content nor changes any game mesh. Change station_id to an existing supported station. The boxes are temporary guides and must not be selected for prop export.

import bpy, json, urllib.request
from mathutils import Vector, Matrix

station_id = "blackjack:0"
asset = "blackjack"
anchor = next(
o for o in bpy.context.scene.objects
if "betworld_entity" in o
and json.loads(o["betworld_entity"]).get("id") == station_id
)
with urllib.request.urlopen(
"https://docs.betworld.gg/game-model-reference.json", timeout=30
) as response:
reference = json.load(response)

guides = bpy.data.collections.new("TEMP control clearance guides")
bpy.context.scene.collection.children.link(guides)

for control in reference["games"][asset]["controls"]:
bounds = control["boundsWorld"]
if bounds is None:
continue
lo, hi = Vector(bounds["min"]), Vector(bounds["max"])
center, size = (lo + hi) / 2, hi - lo
# Bounds are already world-scaled, but remain station-local.
local_center = Vector((center.x, -center.z, center.y))
dimensions = Vector((size.x, size.z, size.y))
padding = 0.08 # Visual working margin, not a complete approach envelope.
bpy.ops.mesh.primitive_cube_add(size=1)
box = bpy.context.object
box.name = "TEMP " + control["action"]
for collection in list(box.users_collection):
collection.objects.unlink(box)
guides.objects.link(box)
box.matrix_world = (
anchor.matrix_world
@ Matrix.Translation(local_center)
@ Matrix.Diagonal(Vector((
dimensions.x + padding,
dimensions.y + padding,
dimensions.z + padding, 1
)))
)
box.display_type = 'WIRE'
box.hide_render = True
box.hide_select = True

The margin is an authoring aid, not a validated reach/collision rule. Also mark live screens, card paths, coin/ball travel and approach space described by the game's guide. Delete or exclude the temporary collection before export. The uploader can include selected mesh guides even if they were intended only as helpers.

Diagnose common mistakes​

SymptomCheck
Everything is about 1.568 times too largeNative source scale may have been applied twice
Screen frame fits the GLB but not the gameYou may have omitted a generated overlay or used a legacy mount as current geometry
Buttons fit from above but cannot be seen while playingReview eye-height sightlines and the front approach
A hollow prop blocks movementThe current prop collider is its box; split solid pieces
A rotating machine leaves trim/rug behindEach prop is a separate entity; apply the same assembly transform
New uploaded button does nothingProps have no user-authored action binding
A display has no controls entriesCheck its guide for runtime screen interaction regions
Coin or ball clips through a signStatic bounds do not cover the animation envelope
Model looks fine locally but is absent in the worldUpload asset, save its prop entity, publish the draft and join that published revision

Use the complete workflow and per-game guides for the rest of the process.