Initial commit for testing/fixing a deprecated godot-colyseus addon

This commit is contained in:
2026-01-10 11:12:02 -05:00
commit 081a5fcf1a
76 changed files with 3456 additions and 0 deletions

315
scripts/hotas_mapper.gd Normal file
View File

@@ -0,0 +1,315 @@
extends CanvasLayer
@export var jet_path: NodePath
@export var config_path: String = "user://hotas_mapping.cfg"
@export var axis_capture_threshold: float = 0.35
@export var toggle_action: String = "toggle_hotas_mapper"
@export var panel_position: Vector2 = Vector2(12, 12)
@export var panel_size: Vector2 = Vector2(520, 360)
const AXIS_CONFIG = [
{
"name": "Roll",
"axis_prop": "roll_axis",
"invert_prop": "roll_invert",
"device_prop": "roll_device_id",
},
{
"name": "Pitch",
"axis_prop": "pitch_axis",
"invert_prop": "pitch_invert",
"device_prop": "pitch_device_id",
},
{
"name": "Yaw",
"axis_prop": "yaw_axis",
"invert_prop": "yaw_invert",
"device_prop": "yaw_device_id",
},
{
"name": "Throttle",
"axis_prop": "throttle_axis",
"invert_prop": "throttle_invert",
"signed_prop": "throttle_signed",
"device_prop": "throttle_device_id",
},
{
"name": "Strafe",
"axis_prop": "strafe_axis",
"invert_prop": "strafe_invert",
"device_prop": "strafe_device_id",
},
{
"name": "Lift",
"axis_prop": "lift_axis",
"invert_prop": "lift_invert",
"device_prop": "lift_device_id",
},
]
var _jet: Node
var _panel: PanelContainer
var _status_label: Label
var _device_label: Label
var _rows := {}
var _listening_axis: String = ""
func _ready() -> void:
_jet = get_node_or_null(jet_path)
_build_ui()
_load_config()
_refresh_labels()
func _unhandled_input(event: InputEvent) -> void:
if _is_toggle_event(event):
visible = not visible
if not visible:
_listening_axis = ""
_refresh_labels()
get_viewport().set_input_as_handled()
func _input(event: InputEvent) -> void:
if not visible:
return
if _listening_axis.is_empty():
return
if event is InputEventJoypadMotion:
if abs(event.axis_value) < axis_capture_threshold:
return
_apply_axis_mapping(_listening_axis, event.axis, event.device)
_listening_axis = ""
_status_label.text = "Axis captured."
_refresh_labels()
func _build_ui() -> void:
_panel = PanelContainer.new()
_panel.name = "HotasMapper"
_panel.anchor_left = 0.0
_panel.anchor_top = 0.0
_panel.anchor_right = 0.0
_panel.anchor_bottom = 0.0
_panel.offset_left = panel_position.x
_panel.offset_top = panel_position.y
_panel.offset_right = panel_position.x + panel_size.x
_panel.offset_bottom = panel_position.y + panel_size.y
add_child(_panel)
var root := VBoxContainer.new()
root.size_flags_vertical = Control.SIZE_EXPAND_FILL
root.size_flags_horizontal = Control.SIZE_EXPAND_FILL
root.add_theme_constant_override("separation", 8)
_panel.add_child(root)
var header := HBoxContainer.new()
header.size_flags_horizontal = Control.SIZE_EXPAND_FILL
root.add_child(header)
var title := Label.new()
title.text = "HOTAS Axis Mapper"
header.add_child(title)
var spacer := Control.new()
spacer.size_flags_horizontal = Control.SIZE_EXPAND_FILL
header.add_child(spacer)
var close_button := Button.new()
close_button.text = "Close"
close_button.pressed.connect(_on_close_pressed)
header.add_child(close_button)
_device_label = Label.new()
_device_label.text = _get_device_text()
root.add_child(_device_label)
_status_label = Label.new()
_status_label.text = "Click Map, then move the desired axis. Toggle: %s" % _get_toggle_hint()
root.add_child(_status_label)
for config in AXIS_CONFIG:
root.add_child(_build_axis_row(config))
func _build_axis_row(config: Dictionary) -> Control:
var row := HBoxContainer.new()
row.size_flags_horizontal = Control.SIZE_EXPAND_FILL
row.add_theme_constant_override("separation", 8)
var name_label := Label.new()
name_label.text = config.name
name_label.custom_minimum_size = Vector2(120, 0)
row.add_child(name_label)
var map_button := Button.new()
map_button.text = "Map"
map_button.pressed.connect(_on_map_pressed.bind(config.axis_prop))
row.add_child(map_button)
var axis_label := Label.new()
axis_label.text = "Axis: ?"
axis_label.custom_minimum_size = Vector2(120, 0)
row.add_child(axis_label)
var device_label := Label.new()
device_label.text = "Dev: ?"
device_label.custom_minimum_size = Vector2(160, 0)
row.add_child(device_label)
var invert_check := CheckBox.new()
invert_check.text = "Invert"
invert_check.toggled.connect(_on_invert_toggled.bind(config.invert_prop))
row.add_child(invert_check)
var signed_check: CheckBox = null
if config.has("signed_prop"):
signed_check = CheckBox.new()
signed_check.text = "Signed"
signed_check.toggled.connect(_on_signed_toggled.bind(config.signed_prop))
row.add_child(signed_check)
_rows[config.axis_prop] = {
"axis_label": axis_label,
"device_label": device_label,
"map_button": map_button,
"invert_check": invert_check,
"signed_check": signed_check,
}
return row
func _on_map_pressed(axis_prop: String) -> void:
if _listening_axis == axis_prop:
_listening_axis = ""
_status_label.text = "Mapping cancelled."
else:
_listening_axis = axis_prop
_status_label.text = "Listening for %s axis..." % axis_prop
_refresh_labels()
func _on_close_pressed() -> void:
_listening_axis = ""
visible = false
func _on_invert_toggled(pressed: bool, invert_prop: String) -> void:
if _jet == null:
return
_jet.set(invert_prop, pressed)
_save_config()
func _on_signed_toggled(pressed: bool, signed_prop: String) -> void:
if _jet == null:
return
_jet.set(signed_prop, pressed)
_save_config()
func _apply_axis_mapping(axis_prop: String, axis_index: int, device_id: int) -> void:
if _jet == null:
return
_jet.set(axis_prop, axis_index)
if device_id >= 0:
var device_prop = _get_device_prop(axis_prop)
if not device_prop.is_empty():
_jet.set(device_prop, device_id)
_jet.set("joy_device_id", device_id)
_save_config()
_device_label.text = _get_device_text()
func _refresh_labels() -> void:
if _jet == null:
return
_device_label.text = _get_device_text()
for config in AXIS_CONFIG:
var axis_prop: String = config.axis_prop
var row = _rows.get(axis_prop, null)
if row == null:
continue
row["axis_label"].text = "Axis: %d" % int(_jet.get(axis_prop))
var device_prop: String = config.device_prop
var device_id: int = int(_jet.get(device_prop))
row["device_label"].text = _get_device_label(device_id)
var invert_prop: String = config.invert_prop
row["invert_check"].set_pressed_no_signal(bool(_jet.get(invert_prop)))
if config.has("signed_prop") and row["signed_check"] != null:
row["signed_check"].set_pressed_no_signal(bool(_jet.get(config.signed_prop)))
var map_button: Button = row["map_button"]
if _listening_axis == axis_prop:
map_button.text = "Listening..."
else:
map_button.text = "Map"
func _load_config() -> void:
if _jet == null:
return
var config := ConfigFile.new()
var err = config.load(config_path)
if err != OK:
return
for entry in AXIS_CONFIG:
var axis_prop: String = entry.axis_prop
if config.has_section_key("axes", axis_prop):
_jet.set(axis_prop, int(config.get_value("axes", axis_prop)))
var invert_prop: String = entry.invert_prop
if config.has_section_key("invert", invert_prop):
_jet.set(invert_prop, bool(config.get_value("invert", invert_prop)))
var device_prop: String = entry.device_prop
if config.has_section_key("devices", device_prop):
_jet.set(device_prop, int(config.get_value("devices", device_prop)))
if entry.has("signed_prop"):
var signed_prop: String = entry.signed_prop
if config.has_section_key("flags", signed_prop):
_jet.set(signed_prop, bool(config.get_value("flags", signed_prop)))
if config.has_section_key("device", "joy_device_id"):
_jet.set("joy_device_id", int(config.get_value("device", "joy_device_id")))
func _save_config() -> void:
if _jet == null:
return
var config := ConfigFile.new()
for entry in AXIS_CONFIG:
var axis_prop: String = entry.axis_prop
config.set_value("axes", axis_prop, int(_jet.get(axis_prop)))
var invert_prop: String = entry.invert_prop
config.set_value("invert", invert_prop, bool(_jet.get(invert_prop)))
var device_prop: String = entry.device_prop
config.set_value("devices", device_prop, int(_jet.get(device_prop)))
if entry.has("signed_prop"):
var signed_prop: String = entry.signed_prop
config.set_value("flags", signed_prop, bool(_jet.get(signed_prop)))
config.set_value("device", "joy_device_id", int(_jet.get("joy_device_id")))
config.save(config_path)
func _get_device_text() -> String:
if _jet == null:
return "Device: none"
var device_id: int = int(_jet.get("joy_device_id"))
if device_id < 0:
var pads = Input.get_connected_joypads()
if pads.is_empty():
return "Device: none"
device_id = pads[0]
var name = Input.get_joy_name(device_id)
return "Device: %s (id %d)" % [name, device_id]
func _get_device_label(device_id: int) -> String:
if device_id < 0:
return "Dev: auto"
var name = Input.get_joy_name(device_id)
if name.is_empty():
return "Dev: %d" % device_id
return "Dev: %s (%d)" % [name, device_id]
func _get_device_prop(axis_prop: String) -> String:
for entry in AXIS_CONFIG:
if entry.axis_prop == axis_prop:
return entry.device_prop
return ""
func _is_toggle_event(event: InputEvent) -> bool:
if InputMap.has_action(toggle_action):
return event.is_action_pressed(toggle_action)
if event is InputEventKey and event.pressed and not event.echo:
return event.keycode == KEY_F1
return false
func _get_toggle_hint() -> String:
if InputMap.has_action(toggle_action):
return toggle_action
return "F1"

View File

@@ -0,0 +1 @@
uid://bj8dpyx6m80px

130
scripts/hud.gd Normal file
View File

@@ -0,0 +1,130 @@
extends CanvasLayer
@export var player_path: NodePath
@export var camera_path: NodePath
@export var vector_scale: float = 2.5
@export var max_radius: float = 140.0
@export var gizmo_margin: Vector2 = Vector2(140, 140)
@export var gizmo_axis_length: float = 55.0
@export var gizmo_axis_width: float = 2.0
@export var velocity_line_width: float = 3.0
@export var show_axis_debug: bool = true
var _velocity_line: Line2D
var _axis_x: Line2D
var _axis_y: Line2D
var _axis_z: Line2D
var _vector_label: Label
var _axis_label: Label
var _player: RigidBody3D
var _camera: Camera3D
func _ready() -> void:
_velocity_line = _get_or_create_velocity_line()
_axis_x = _get_or_create_axis_line("AxisX", Color(0.95, 0.2, 0.2, 0.9))
_axis_y = _get_or_create_axis_line("AxisY", Color(0.2, 0.9, 0.4, 0.9))
_axis_z = _get_or_create_axis_line("AxisZ", Color(0.2, 0.5, 1.0, 0.9))
_vector_label = _get_or_create_vector_label()
_axis_label = _get_or_create_axis_label()
_player = get_node_or_null(player_path)
_camera = get_node_or_null(camera_path)
_axis_label.visible = show_axis_debug
func _process(_delta: float) -> void:
if _player == null or _camera == null:
return
var velocity = _player.linear_velocity
var cam_basis = _camera.global_transform.basis
var local_velocity = cam_basis.inverse() * velocity
var arrow = Vector2(local_velocity.x, -local_velocity.y) * vector_scale
if arrow.length() > max_radius:
arrow = arrow.normalized() * max_radius
var viewport_size = get_viewport().get_visible_rect().size
var center = Vector2(
viewport_size.x - gizmo_margin.x,
viewport_size.y - gizmo_margin.y
)
_velocity_line.points = PackedVector2Array([center, center + arrow])
var player_basis = _player.global_transform.basis
var rel_basis = cam_basis.inverse() * player_basis
_axis_x.points = PackedVector2Array([
center,
center + Vector2(rel_basis.x.x, -rel_basis.x.y) * gizmo_axis_length
])
_axis_y.points = PackedVector2Array([
center,
center + Vector2(rel_basis.y.x, -rel_basis.y.y) * gizmo_axis_length
])
_axis_z.points = PackedVector2Array([
center,
center + Vector2(rel_basis.z.x, -rel_basis.z.y) * gizmo_axis_length
])
_vector_label.text = "Velocity: (%.1f, %.1f, %.1f) m/s | Speed: %.1f" % [
velocity.x,
velocity.y,
velocity.z,
velocity.length(),
]
if show_axis_debug and _axis_label != null:
if _player.has_method("get_axis_debug_text"):
_axis_label.text = _player.get_axis_debug_text()
func _get_or_create_velocity_line() -> Line2D:
var existing: Line2D = get_node_or_null("VelocityLine")
if existing != null:
return existing
var line := Line2D.new()
line.name = "VelocityLine"
line.width = velocity_line_width
line.default_color = Color(1, 0.7, 0.2, 0.9)
line.antialiased = true
add_child(line)
return line
func _get_or_create_axis_line(name: String, color: Color) -> Line2D:
var existing: Line2D = get_node_or_null(name)
if existing != null:
return existing
var line := Line2D.new()
line.name = name
line.width = gizmo_axis_width
line.default_color = color
line.antialiased = true
add_child(line)
return line
func _get_or_create_vector_label() -> Label:
var existing: Label = get_node_or_null("VectorLabel")
if existing != null:
return existing
var label := Label.new()
label.name = "VectorLabel"
label.text = "Velocity:"
label.set_anchors_and_offsets_preset(Control.PRESET_TOP_LEFT)
label.offset_left = 12.0
label.offset_top = 12.0
label.offset_right = 520.0
label.offset_bottom = 40.0
add_child(label)
return label
func _get_or_create_axis_label() -> Label:
var existing: Label = get_node_or_null("AxisLabel")
if existing != null:
return existing
var label := Label.new()
label.name = "AxisLabel"
label.text = "Axis:"
label.set_anchors_and_offsets_preset(Control.PRESET_BOTTOM_LEFT)
label.offset_left = 12.0
label.offset_top = -60.0
label.offset_right = 520.0
label.offset_bottom = -12.0
add_child(label)
return label

1
scripts/hud.gd.uid Normal file
View File

@@ -0,0 +1 @@
uid://csqjx18o6oblo

194
scripts/jet_controller.gd Normal file
View File

@@ -0,0 +1,194 @@
extends RigidBody3D
@export var joy_device_id: int = -1
@export var pitch_axis: int = 1
@export var pitch_invert: bool = true
@export var pitch_device_id: int = -1
@export var roll_axis: int = 0
@export var roll_invert: bool = false
@export var roll_device_id: int = -1
@export var yaw_axis: int = 2
@export var yaw_invert: bool = false
@export var yaw_device_id: int = -1
@export var throttle_axis: int = 3
@export var throttle_invert: bool = true
@export var throttle_signed: bool = true
@export var throttle_device_id: int = -1
@export var strafe_axis: int = 4
@export var strafe_invert: bool = false
@export var strafe_device_id: int = -1
@export var lift_axis: int = 5
@export var lift_invert: bool = false
@export var lift_device_id: int = -1
@export var stick_deadzone: float = 0.08
@export var throttle_deadzone: float = 0.02
@export var max_thrust: float = 7500.0
@export var strafe_thrust: float = 3500.0
@export var lift_thrust: float = 3500.0
@export var torque_strength: float = 2000.0
@export var throttle_response: float = 3.0
@export var stick_response: float = 6.0
@export var stick_expo: float = 1.6
@export var max_speed: float = 180.0
@export var max_angular_speed: float = 2.6
@export var vector_line_path: NodePath = NodePath("DisplacementVector")
@export var vector_scale: float = 0.05
@export var max_vector_length: float = 20.0
var _device_id: int = -1
var _current_throttle: float = 0.0
var _vector_line: Node
var _axis_state := {
"roll": 0.0,
"pitch": 0.0,
"yaw": 0.0,
"throttle": 0.0,
"strafe": 0.0,
"lift": 0.0,
}
var _axis_smoothed := {
"roll": 0.0,
"pitch": 0.0,
"yaw": 0.0,
"strafe": 0.0,
"lift": 0.0,
}
func _ready() -> void:
_vector_line = get_node_or_null(vector_line_path)
_device_id = _resolve_joypad()
if _device_id == -1:
push_warning("No HOTAS detected. Connect the X56 or set joy_device_id.")
func _physics_process(delta: float) -> void:
_device_id = _resolve_joypad()
if _device_id == -1:
_update_vector_line()
return
var roll = _shape_axis(_read_axis(_resolve_axis_device(roll_device_id), roll_axis, stick_deadzone, roll_invert))
var pitch = _shape_axis(_read_axis(_resolve_axis_device(pitch_device_id), pitch_axis, stick_deadzone, pitch_invert))
var yaw = _shape_axis(_read_axis(_resolve_axis_device(yaw_device_id), yaw_axis, stick_deadzone, yaw_invert))
var strafe = _shape_axis(_read_axis(_resolve_axis_device(strafe_device_id), strafe_axis, stick_deadzone, strafe_invert))
var lift = _shape_axis(_read_axis(_resolve_axis_device(lift_device_id), lift_axis, stick_deadzone, lift_invert))
var raw_throttle = _read_axis(_resolve_axis_device(throttle_device_id), throttle_axis, throttle_deadzone, throttle_invert)
var target_throttle: float
if throttle_signed:
target_throttle = clamp(raw_throttle, -1.0, 1.0)
else:
target_throttle = clamp((raw_throttle + 1.0) * 0.5, 0.0, 1.0)
_current_throttle = lerp(
_current_throttle,
target_throttle,
clamp(throttle_response * delta, 0.0, 1.0)
)
roll = _smooth_axis("roll", roll, delta)
pitch = _smooth_axis("pitch", pitch, delta)
yaw = _smooth_axis("yaw", yaw, delta)
strafe = _smooth_axis("strafe", strafe, delta)
lift = _smooth_axis("lift", lift, delta)
_axis_state["roll"] = roll
_axis_state["pitch"] = pitch
_axis_state["yaw"] = yaw
_axis_state["throttle"] = _current_throttle
_axis_state["strafe"] = strafe
_axis_state["lift"] = lift
var basis = global_transform.basis
var forward = -basis.z
var right = basis.x
var up = basis.y
var thrust_force = forward * (_current_throttle * max_thrust)
var strafe_force = right * (strafe * strafe_thrust)
var lift_force = up * (lift * lift_thrust)
apply_central_force(thrust_force + strafe_force + lift_force)
var local_angular = basis.inverse() * angular_velocity
var desired_angular = Vector3(pitch, yaw, -roll) * max_angular_speed
var torque_local = (desired_angular - local_angular) * torque_strength
apply_torque(basis * torque_local)
if max_speed > 0.0 and linear_velocity.length() > max_speed:
linear_velocity = linear_velocity.limit_length(max_speed)
if max_angular_speed > 0.0 and angular_velocity.length() > max_angular_speed:
angular_velocity = angular_velocity.limit_length(max_angular_speed)
_update_vector_line()
func get_axis_debug_text() -> String:
if _device_id == -1:
return "No HOTAS detected"
return "Roll: %.2f (d%d) Pitch: %.2f (d%d) Yaw: %.2f (d%d)\nThrottle: %.2f (d%d) Strafe: %.2f (d%d) Lift: %.2f (d%d)" % [
_axis_state["roll"],
_resolve_axis_device(roll_device_id),
_axis_state["pitch"],
_resolve_axis_device(pitch_device_id),
_axis_state["yaw"],
_resolve_axis_device(yaw_device_id),
_axis_state["throttle"],
_resolve_axis_device(throttle_device_id),
_axis_state["strafe"],
_resolve_axis_device(strafe_device_id),
_axis_state["lift"],
_resolve_axis_device(lift_device_id),
]
func get_joypad_id() -> int:
return _device_id
func _resolve_joypad() -> int:
if joy_device_id >= 0:
return joy_device_id
var pads = Input.get_connected_joypads()
if pads.is_empty():
return -1
return pads[0]
func _resolve_axis_device(axis_device_id: int) -> int:
if axis_device_id >= 0:
return axis_device_id
return _device_id
func _read_axis(device_id: int, axis: int, deadzone: float, invert: bool) -> float:
if axis < 0 or device_id < 0:
return 0.0
var value = Input.get_joy_axis(device_id, axis)
if invert:
value = -value
var magnitude = abs(value)
if magnitude <= deadzone:
return 0.0
var scaled = (magnitude - deadzone) / (1.0 - deadzone)
return scaled * sign(value)
func _shape_axis(value: float) -> float:
if stick_expo <= 1.0:
return value
return sign(value) * pow(abs(value), stick_expo)
func _smooth_axis(name: String, value: float, delta: float) -> float:
if stick_response <= 0.0:
_axis_smoothed[name] = value
return value
var t = clamp(stick_response * delta, 0.0, 1.0)
_axis_smoothed[name] = lerp(_axis_smoothed[name], value, t)
return _axis_smoothed[name]
func _update_vector_line() -> void:
if _vector_line == null:
return
if not _vector_line.has_method("set_vector"):
return
var local_velocity = global_transform.basis.inverse() * linear_velocity
var clamped = local_velocity.limit_length(max_vector_length)
_vector_line.set_vector(clamped * vector_scale)

View File

@@ -0,0 +1 @@
uid://bs6rfdeujndbp

109
scripts/network.gd Normal file
View File

@@ -0,0 +1,109 @@
# res://scripts/network.gd
extends Node
signal connected(room_id: String)
signal disconnected(reason: String)
signal state_changed()
signal message_received(type: String, payload: Variant)
signal error(msg: String)
const colyseus := preload("res://addons/godot_colyseus/lib/colyseus.gd")
const RoomState := preload("res://scripts/room_state.gd")
const Room := preload("res://addons/godot_colyseus/lib/room.gd")
var client: colyseus.Client
var room: Room
var state: RoomState
var _connecting := false
var _endpoint := ""
#func is_connected() -> bool:
#return room != null
func connect_and_join(endpoint: String, room_name: String = "my_room") -> void:
if _connecting:
return
if room != null:
emit_signal("error", "Already connected.")
return
_connecting = true
_endpoint = endpoint
client = colyseus.Client.new(endpoint)
var promise = client.join_or_create(RoomState, room_name)
await promise.completed
_connecting = false
if promise.get_state() == promise.State.Failed:
var msg := "Join failed: %s" % str(promise.get_error())
emit_signal("error", msg)
return
# old addon: result is a property
room = promise.result
if room == null:
emit_signal("error", "Join succeeded but room is null (promise.result).")
return
state = room.get_state() as RoomState
if state == null:
emit_signal("error", "Joined but could not cast state to RoomState.")
return
# --- wire listeners ---
room.on_state_change.on(Callable(self, "_on_state_change"))
# if addon supports on_leave / on_error, hook them too (safe-guarded)
if "on_leave" in room:
room.on_leave.on(Callable(self, "_on_room_left"))
if "on_error" in room:
room.on_error.on(Callable(self, "_on_room_error"))
emit_signal("connected", room.room_id)
func leave() -> void:
if room == null:
return
# some addons use room.leave(), some room.disconnect()
if room.has_method("leave"):
room.leave()
elif room.has_method("disconnect"):
pass
#room.disconnect()
_cleanup("left")
func send(type: String, payload: Variant = null) -> void:
if room == null:
emit_signal("error", "Cannot send, not connected.")
return
room.send(type, payload)
func listen_message(type: String) -> void:
if room == null:
emit_signal("error", "Cannot listen, not connected.")
return
room.on_message(type).on(Callable(self, "_on_message").bind(type))
func reconnect(room_name: String = "my_room") -> void:
_cleanup("reconnect")
await connect_and_join(_endpoint, room_name)
func _on_state_change(_new_state = null) -> void:
emit_signal("state_changed")
func _on_message(payload: Variant, type: String) -> void:
emit_signal("message_received", type, payload)
func _on_room_left(code = null) -> void:
_cleanup("room_left %s" % str(code))
func _on_room_error(code = null, message = null) -> void:
_cleanup("room_error %s %s" % [str(code), str(message)])
func _cleanup(reason: String) -> void:
room = null
state = null
emit_signal("disconnected", reason)

1
scripts/network.gd.uid Normal file
View File

@@ -0,0 +1 @@
uid://d0amrs41uhwql

10
scripts/room_state.gd Normal file
View File

@@ -0,0 +1,10 @@
# res://scripts/room_state.gd
extends "res://addons/godot_colyseus/lib/schema.gd"
class_name RoomState
var mySynchronizedProperty: String = "Hello world"
static func define_fields():
return [
Field.new("mySynchronizedProperty", Types.STRING),
]

View File

@@ -0,0 +1 @@
uid://dlh5cvfm6xapu

22
scripts/vector_line_3d.gd Normal file
View File

@@ -0,0 +1,22 @@
extends MeshInstance3D
@export var color: Color = Color(0.1, 0.8, 1.0, 0.9)
var _mesh: ImmediateMesh
var _material: StandardMaterial3D
func _ready() -> void:
_mesh = ImmediateMesh.new()
mesh = _mesh
_material = StandardMaterial3D.new()
_material.shading_mode = BaseMaterial3D.SHADING_MODE_UNSHADED
_material.albedo_color = color
func set_vector(end_point: Vector3) -> void:
if _mesh == null:
return
_mesh.clear_surfaces()
_mesh.surface_begin(Mesh.PRIMITIVE_LINES, _material)
_mesh.surface_add_vertex(Vector3.ZERO)
_mesh.surface_add_vertex(end_point)
_mesh.surface_end()

View File

@@ -0,0 +1 @@
uid://3ierf3uelmp8