This commit is contained in:
Hamcha 2020-07-22 17:34:04 +02:00
parent 3d57f3d839
commit b77326eb80
Signed by: Hamcha
GPG Key ID: 41467804B19A3315
39 changed files with 211 additions and 1624 deletions

View File

@ -185,6 +185,7 @@ rect_scale = Vector2( 0.5, 0.5 )
[node name="ActivationRange" type="Area2D" parent="."]
visible = false
input_pickable = false
script = ExtResource( 6 )
[node name="CollisionShape2D" type="CollisionShape2D" parent="ActivationRange"]

View File

@ -66,6 +66,7 @@ one_shot = true
[node name="ActivationRange" type="Area2D" parent="."]
visible = false
input_pickable = false
script = ExtResource( 3 )
[node name="CollisionShape2D" type="CollisionShape2D" parent="ActivationRange"]
@ -73,6 +74,7 @@ position = Vector2( 16, 16 )
shape = SubResource( 8 )
[node name="CloseRange" type="Area2D" parent="."]
input_pickable = false
script = ExtResource( 3 )
[node name="CollisionShape2D" type="CollisionShape2D" parent="CloseRange"]

View File

@ -52,7 +52,7 @@ func refresh_sprite() -> void:
$Light2D.rotation = rot
$ActivationRange.rotation = rot
func _physics_process(delta: float) -> void:
func _physics_process(_delta: float) -> void:
if Engine.editor_hint:
return
manager.power_usage = max(1e-3, MAX_USAGE * strength)

View File

@ -14,7 +14,6 @@ extents = Vector2( 72, 72 )
[node name="Engine" type="StaticBody2D"]
script = ExtResource( 2 )
max_force = 0.05
[node name="CollisionShape2D" type="CollisionShape2D" parent="."]
position = Vector2( 48, 48 )
@ -36,6 +35,7 @@ energy = 0.002
[node name="ActivationRange" type="Area2D" parent="."]
visible = false
input_pickable = false
script = ExtResource( 1 )
[node name="CollisionShape2D" type="CollisionShape2D" parent="ActivationRange"]

View File

@ -38,6 +38,7 @@ __meta__ = {
[node name="ActivationRange" type="Area2D" parent="."]
visible = false
input_pickable = false
script = ExtResource( 4 )
[node name="CollisionShape2D" type="CollisionShape2D" parent="ActivationRange"]

View File

@ -97,6 +97,7 @@ rect_scale = Vector2( 0.5, 0.5 )
[node name="ActivationRange" type="Area2D" parent="."]
visible = false
position = Vector2( 16, 16 )
input_pickable = false
script = ExtResource( 3 )
[node name="CollisionShape2D" type="CollisionShape2D" parent="ActivationRange"]

View File

@ -5,5 +5,5 @@ class_name GameObjectScanner
func serialize():
return {}
func deserialize(data):
func deserialize(_data):
pass

View File

@ -100,5 +100,5 @@ func draw_circle_arc_poly(center, radius, angle_from, angle_to, color):
points_arc.push_back(center + Vector2(cos(angle_point), sin(angle_point)) * radius)
draw_polygon(points_arc, colors)
func hear(event):
func hear(_event):
pass

View File

@ -24,7 +24,7 @@ position = Vector2( 0, -3 )
shape = SubResource( 1 )
[node name="Earing" type="Area2D" parent="."]
monitorable = false
input_pickable = false
collision_layer = 32
collision_mask = 32

View File

@ -111,3 +111,26 @@ func _draw():
func _area_moved():
scout()
update()
func serialize():
var subareas = {}
for child in get_children():
subareas[child.name] = {
"transform": child.transform
}
return {
"name": area_name,
"wall_path": wall_tilemap,
"base_path": base_tilemap,
"subareas": subareas
}
func deserialize(data):
for subarea in data.subareas:
var node = Node2D.new()
node.name = subarea
node.transform = data.subareas[subarea].transform
add_child(node)
area_name = data.name
wall_tilemap = data.wall_path
base_tilemap = data.base_path

View File

@ -14,6 +14,7 @@ a = Vector2( -16, 16 )
b = Vector2( 48, 16 )
[node name="ElProbe" type="Area2D"]
input_pickable = false
collision_layer = 4
collision_mask = 4
script = ExtResource( 1 )

View File

@ -21,7 +21,8 @@ static func to_letter(num: int) -> String:
return "Α"
elif num < 0:
letters = "αβγδεζηθικλμνξοπρστυφχψω"
num = abs(num)
if num < 0:
num = -num
var out = ""
var base = letters.length()
while num > 0:

View File

@ -4,7 +4,7 @@ var thread
var mutex
var sem
var gotm_mode = false
var threaded = true
var time_max = 100 # Milliseconds.
var queue = []
@ -13,19 +13,15 @@ var pending = {}
func _lock(_caller):
mutex.lock()
func _unlock(_caller):
mutex.unlock()
func _post(_caller):
sem.post()
func _wait(_caller):
sem.wait()
func queue_resource(path, p_in_front = false):
_lock("queue_resource")
if path in pending:
@ -48,7 +44,6 @@ func queue_resource(path, p_in_front = false):
_unlock("queue_resource")
return
func cancel_resource(path):
_lock("cancel_resource")
if path in pending:
@ -57,9 +52,8 @@ func cancel_resource(path):
pending.erase(path)
_unlock("cancel_resource")
func get_progress(path):
if gotm_mode:
if not threaded:
return 1.0
_lock("get_progress")
var ret = -1
@ -71,9 +65,8 @@ func get_progress(path):
_unlock("get_progress")
return ret
func is_ready(path):
if gotm_mode:
if not threaded:
return true
var ret
_lock("is_ready")
@ -84,9 +77,8 @@ func is_ready(path):
_unlock("is_ready")
return ret
func _wait_for_resource(res, path):
if gotm_mode:
if not threaded:
return get_resource(path)
_unlock("wait_for_resource")
while true:
@ -97,9 +89,8 @@ func _wait_for_resource(res, path):
return pending[path]
_unlock("wait_for_resource")
func get_resource(path):
if gotm_mode:
if not threaded:
return load(path)
_lock("get_resource")
if path in pending:
@ -123,7 +114,6 @@ func get_resource(path):
_unlock("return")
return ResourceLoader.load(path)
func thread_process():
_wait("thread_process")
_lock("process")
@ -143,16 +133,15 @@ func thread_process():
queue.erase(res)
_unlock("process")
func thread_func(_u):
while true:
thread_process()
func start(gotm: bool):
gotm_mode = gotm
if not gotm:
mutex = Mutex.new()
sem = Semaphore.new()
thread = Thread.new()
thread.start(self, "thread_func", 0)
func start(use_threads: bool):
threaded = use_threads
if not threaded:
return
mutex = Mutex.new()
sem = Semaphore.new()
thread = Thread.new()
thread.start(self, "thread_func", 0)

View File

@ -4,7 +4,6 @@
script/source = "extends Node
func _ready():
$\"/root/Multiplayer\".gotm_mode = true # Faster startup
$\"/root/Multiplayer\".host()
"

View File

@ -14,7 +14,6 @@ var writing = false
func _ready() -> void:
randomize()
ui.connect("command", world, "process_command")
if netgame.hosting:
world.load_map(netgame.get_current_map())
world.map.current_ship_position = Vector2(randf() * 1e4, randf() * 1e4)
@ -58,11 +57,14 @@ master func broadcast_zone(message: String, origin: Vector2, radius: float) -> v
var shape = CircleShape2D.new()
shape.radius = radius
var query = Physics2DShapeQueryParameters.new()
query.collide_with_areas = true
query.collide_with_bodies = false
query.collision_layer = 32
query.transform = Transform(world.transform.translated(origin))
query.transform.origin = origin
query.set_shape(shape)
var res = physics.intersect_shape(query, 100)
print(res)
for col in res:
rpc_id(col.collider.get_network_master(), "add_log", message)
master func broadcast(message: String) -> void:
rpc("add_log", message)

View File

@ -14,7 +14,7 @@ const SYSTEMS_UPDATE_INTERVAL = 10
# Master server data
const MASTER_SERVER_ADDR = "fgms.zyg.ovh"
const MASTER_SERVER_UDP_PORT = 9434
const MS_GAME_CODE = "odyssey-0-a1"
const MS_GAME_CODE = "odyssey-0-a2"
const GOTM_OVERRIDE = false
# Master server entry
@ -22,7 +22,6 @@ var ms_active = false
var ms_key = ""
var server_name = ""
onready var gotm_mode = Gotm.is_live() or GOTM_OVERRIDE
var hosting = false
export var player_name = ""
@ -34,8 +33,6 @@ onready var scene_manager = $"/root/SceneManager"
func _ready():
player_name = "tider-" + str(randi() % 1000)
if gotm_mode:
Gotm.connect("lobby_changed", self, "_lobby_changed")
func bind_events():
get_tree().connect("network_peer_connected", self, "_player_connected")
@ -76,22 +73,17 @@ func host():
yield(get_tree().create_timer(0.3), "timeout")
# Run port forwarding/nat punchthrough if the platform doesn't do it already
if not gotm_mode:
print("Running UPNP magicks")
if discover_upnp() == UPNP.UPNP_RESULT_SUCCESS:
print("UPNP mapping added")
else:
push_warning("UPNP magicks fail, punching NAT in the face")
yield(punch_nat(), "completed")
print("Running UPNP magicks")
if discover_upnp() == UPNP.UPNP_RESULT_SUCCESS:
print("UPNP mapping added")
else:
push_warning("UPNP magicks fail, punching NAT in the face")
yield(punch_nat(), "completed")
server_name = player_name + "'s server"
player_info[1] = { "name": player_name }
round_info = { "map": "odyssey" }
if gotm_mode:
# Add to master server before hosting (in GOTM mode)
create_ms_entry()
bind_events()
var peer = NetworkedMultiplayerENet.new()
peer.compression_mode = NetworkedMultiplayerENet.COMPRESS_FASTLZ
@ -113,9 +105,8 @@ func host():
"res://Scenes/Maps/odyssey.tscn"
])
if not gotm_mode:
# Add to master server after hosting
create_ms_entry()
# Add to master server after hosting
create_ms_entry()
func join(server):
scene_manager.enter_loader()
@ -126,13 +117,9 @@ func join(server):
bind_events()
var peer = NetworkedMultiplayerENet.new()
peer.compression_mode = NetworkedMultiplayerENet.COMPRESS_FASTLZ
var addr = null
if gotm_mode:
var success = yield(server.join(), "completed")
addr = Gotm.lobby.host.address
else:
addr = server.address
var addr = server.address
peer.create_client(addr, SERVER_PORT)
get_tree().network_peer = peer
@ -193,20 +180,15 @@ func _ms_request(endpoint: String, data):
push_error("An error occurred in the HTTP request.")
func ms_get_entries():
if gotm_mode:
var fetch = GotmLobbyFetch.new()
var lobbies = yield(fetch.first(), "completed")
emit_signal("ms_updated", "list_games", lobbies)
else:
var http_request = HTTPRequest.new()
add_child(http_request)
http_request.connect("request_completed", self, "_ms_response", ["list_games"])
var error = http_request.request(
"https://" + MASTER_SERVER_ADDR + "/" + MS_GAME_CODE,
["Content-Type: application/json"],
true, HTTPClient.METHOD_GET)
if error != OK:
push_error("An error occurred in the HTTP request.")
var http_request = HTTPRequest.new()
add_child(http_request)
http_request.connect("request_completed", self, "_ms_response", ["list_games"])
var error = http_request.request(
"https://" + MASTER_SERVER_ADDR + "/" + MS_GAME_CODE,
["Content-Type: application/json"],
true, HTTPClient.METHOD_GET)
if error != OK:
push_error("An error occurred in the HTTP request.")
func get_game_data():
return {
@ -217,28 +199,17 @@ func get_game_data():
}
func create_ms_entry():
if gotm_mode:
Gotm.host_lobby(true)
Gotm.lobby.hidden = false
else:
_ms_request("new", {
"game_id": MS_GAME_CODE,
"data": get_game_data()
})
update_ms_entry()
_ms_request("new", {
"game_id": MS_GAME_CODE,
"data": get_game_data()
})
func update_ms_entry():
if gotm_mode:
var data = get_game_data()
Gotm.lobby.name = data.name
for key in data:
Gotm.lobby.set_property(key, data[key])
else:
if ms_active:
_ms_request("update", {
"key": ms_key,
"data": get_game_data()
})
if ms_active:
_ms_request("update", {
"key": ms_key,
"data": get_game_data()
})
var time_left = 30
func _process(delta):
@ -276,6 +247,3 @@ func get_current_map():
return GameWorld.Map.RUNTIME
_:
return GameWorld.Map.EMPTY
func _lobby_changed():
print("Lobby changed ", Gotm.lobby)

View File

@ -9,13 +9,16 @@ var loader = preload("res://Scenes/Loader.tscn")
onready var netgame = $"/root/Multiplayer"
func _ready() -> void:
queue.start(netgame.gotm_mode)
var threads_supported = true
if OS.get_name() == "HTML5":
threads_supported = false
queue.start(threads_supported)
func enter_loader() -> void:
get_tree().change_scene_to(loader)
func load_scene(scene_path: String, dependencies: Array) -> void:
if not netgame.gotm_mode:
if queue.threaded:
target_scene = scene_path
queue.queue_resource(scene_path)
for dep in dependencies:
@ -24,7 +27,7 @@ func load_scene(scene_path: String, dependencies: Array) -> void:
get_tree().change_scene(scene_path)
func _physics_process(_delta: float) -> void:
if not netgame.gotm_mode:
if queue.threaded:
if target_scene != null:
var remaining = queue.pending.size()
for path in queue.pending:

View File

@ -61,11 +61,8 @@ func _process(delta: float):
if Engine.editor_hint:
return
var current_speed_ratio = 0
var engines = get_engine_count()
var max_speed = get_max_speed()
if engines > 0:
current_speed_ratio = current_ship_speed / max_speed
# Ease ship speed/direction changes
if abs(current_ship_direction) > PI*2:
@ -163,19 +160,14 @@ func serialize() -> Dictionary:
data.append([cell, tilemap.get_cellv(cell)])
tilemapdata[tilemap.name] = data
# Get objects
var engines = serialize_children($engines)
var objects = serialize_children($objects)
var lights = serialize_children($lights)
var sockets = serialize_children($sockets)
var pois = serialize_children($pois)
return {
"tilemaps": tilemapdata,
"engines": engines,
"objects": objects,
"lights": lights,
"sockets": sockets,
"pois": pois,
"engines": serialize_children($engines),
"objects": serialize_children($objects),
"lights": serialize_children($lights),
"sockets": serialize_children($sockets),
"pois": serialize_children($pois),
"areas": serialize_children($areas),
"ship": {
"position": current_ship_position,
"target": current_ship_target,
@ -201,6 +193,8 @@ func deserialize(data: Dictionary) -> void:
deserialize_children($lights, data["lights"])
deserialize_children($pois, data["pois"])
deserialize_children($sockets, data["sockets"])
deserialize_children($sockets, data["sockets"])
deserialize_children($areas, data["areas"], true)
# Set ship parameters
current_ship_position = data["ship"]["position"]
@ -223,14 +217,17 @@ func serialize_children(node: Node) -> Dictionary:
}
return data
func deserialize_children(node: Node, data: Dictionary) -> void:
func deserialize_children(node: Node, data: Dictionary, deserialize_first: bool = false) -> void:
for node_name in data:
var node_data = data[node_name] as Dictionary
var node_scene = load(node_data.filename).instance()
node_scene.name = node_name
node_scene.transform = node_data.transform
if deserialize_first:
node_scene.deserialize(node_data.data)
node.add_child(node_scene, true)
node_scene.deserialize(node_data.data)
if not deserialize_first:
node_scene.deserialize(node_data.data)
# Lighting

View File

@ -103,3 +103,5 @@ __meta__ = {
[node name="pois" type="Node2D" parent="."]
z_index = 999
[node name="areas" type="Node2D" parent="."]

View File

@ -21,10 +21,6 @@ func _ready() -> void:
$"/root/Music/BGM".play()
netgame.connect("ms_updated", self, "_ms_update")
request_servers()
if netgame.gotm_mode:
# Hide manual connect
$Popup/MarginContainer/VBoxContainer/Label2.visible = false
$Popup/MarginContainer/VBoxContainer/HBoxContainer.visible = false
func _process(delta: float) -> void:
refresh_server_remaining -= delta
@ -49,14 +45,9 @@ func _ms_update(action, result):
if action == "list_games":
# Reset server list
server_list.clear()
if netgame.gotm_mode:
servers = result
for server in servers:
server_list.add_item(server.name + " (" + server.id + ") - " + str(server.peers.size()) + "/" + str(server.get_property("max_players")) + " players")
else:
servers = result
for server in servers:
server_list.add_item(server.data.name + " (" + server.address + ") - " + str(server.data.players) + "/" + str(server.data.max_players) + " players")
servers = result
for server in servers:
server_list.add_item(server.data.name + " (" + server.address + ") - " + str(server.data.players) + "/" + str(server.data.max_players) + " players")
func set_scale(val) -> void:
scale = val
@ -84,7 +75,7 @@ func _server_addr_changed(new_text: String) -> void:
$Popup/MarginContainer/VBoxContainer/HBoxContainer/Button.disabled = new_text.length() < 1
func _manual_join_pressed():
join_server($Popup/MarginContainer/VBoxContainer/HBoxContainer/LineEdit.text)
join_server({ "address": $Popup/MarginContainer/VBoxContainer/HBoxContainer/LineEdit.text })
func _server_item_clicked(index):
$"/root/Music/BGM".stop()

View File

@ -2,8 +2,6 @@ extends Control
class_name GameUI
signal command(command)
enum ServerMenuItem {
ServerInfo
}
@ -16,7 +14,7 @@ enum PopupName {
onready var logs = $Logs
onready var scene = $"/root/scene"
const CHAT_RADIUS = 32*6
const CHAT_RADIUS = 32*10
func _ready() -> void:
# Add options to menu buttons

View File

@ -1,11 +1,36 @@
[gd_scene load_steps=6 format=2]
[gd_scene load_steps=15 format=2]
[ext_resource path="res://Scenes/UI/SpaceMap.tscn" type="PackedScene" id=1]
[ext_resource path="res://Scenes/UI.gd" type="Script" id=2]
[ext_resource path="res://Scenes/UI/Panels/Logs.tscn" type="PackedScene" id=3]
[ext_resource path="res://Graphics/UI/iosevka-aile-regular.ttf" type="DynamicFontData" id=3]
[ext_resource path="res://Scenes/UI/Panels/ServerInfo.tscn" type="PackedScene" id=4]
[ext_resource path="res://Scenes/UI/Widgets/ResizablePanel.tscn" type="PackedScene" id=5]
[ext_resource path="res://Scenes/UI/Panels/Logs.gd" type="Script" id=6]
[ext_resource path="res://Graphics/UI/iosevka-aile-italic.ttf" type="DynamicFontData" id=7]
[ext_resource path="res://Graphics/UI/iosevka-aile-bold.ttf" type="DynamicFontData" id=8]
[ext_resource path="res://Graphics/UI/iosevka-aile-bolditalic.ttf" type="DynamicFontData" id=9]
[sub_resource type="StyleBoxFlat" id=1]
[sub_resource type="DynamicFont" id=1]
size = 14
use_mipmaps = true
font_data = ExtResource( 9 )
[sub_resource type="DynamicFont" id=2]
size = 14
use_mipmaps = true
font_data = ExtResource( 7 )
[sub_resource type="DynamicFont" id=3]
size = 14
use_mipmaps = true
font_data = ExtResource( 8 )
[sub_resource type="DynamicFont" id=4]
size = 14
use_mipmaps = true
font_data = ExtResource( 3 )
[sub_resource type="StyleBoxFlat" id=5]
bg_color = Color( 0.133333, 0.12549, 0.203922, 0.705882 )
border_width_left = 4
border_width_top = 4
@ -31,11 +56,53 @@ __meta__ = {
[node name="MapPopup" parent="." instance=ExtResource( 1 )]
[node name="Logs" parent="." instance=ExtResource( 3 )]
[node name="Logs" type="Control" parent="."]
margin_left = 10.0
margin_top = 10.0
margin_right = -857.0
margin_bottom = -566.0
margin_right = 475.0
margin_bottom = 273.0
script = ExtResource( 6 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="ResizablePanel" parent="Logs" instance=ExtResource( 5 )]
title = "Logs"
[node name="RichTextLabel" type="RichTextLabel" parent="Logs/ResizablePanel"]
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = 10.0
margin_top = 40.0
margin_right = -10.0
margin_bottom = -40.0
focus_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
custom_fonts/bold_italics_font = SubResource( 1 )
custom_fonts/italics_font = SubResource( 2 )
custom_fonts/bold_font = SubResource( 3 )
custom_fonts/normal_font = SubResource( 4 )
bbcode_enabled = true
selection_enabled = true
__meta__ = {
"_edit_use_anchors_": false
}
[node name="LineEdit" type="LineEdit" parent="Logs/ResizablePanel"]
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = 6.0
margin_top = -30.0
margin_right = -16.0
margin_bottom = -6.0
focus_mode = 1
caret_blink = true
caret_blink_speed = 0.5
__meta__ = {
"_edit_use_anchors_": false
}
[node name="Menu" type="PanelContainer" parent="."]
anchor_left = 1.0
@ -48,7 +115,7 @@ grow_horizontal = 0
grow_vertical = 0
size_flags_horizontal = 8
size_flags_vertical = 8
custom_styles/panel = SubResource( 1 )
custom_styles/panel = SubResource( 5 )
__meta__ = {
"_edit_use_anchors_": false
}
@ -90,3 +157,9 @@ margin_left = 31.2773
margin_top = 46.9222
margin_right = 287.277
margin_bottom = 214.923
[connection signal="chat_message_sent" from="Logs" to="." method="_send_chat"]
[connection signal="focus_entered" from="Logs/ResizablePanel/LineEdit" to="Logs" method="_chat_bar_status" binds= [ true ]]
[connection signal="focus_exited" from="Logs/ResizablePanel/LineEdit" to="Logs" method="_chat_bar_status" binds= [ false ]]
[connection signal="mouse_entered" from="Logs/ResizablePanel/LineEdit" to="Logs" method="_chat_bar_focus" binds= [ true ]]
[connection signal="mouse_exited" from="Logs/ResizablePanel/LineEdit" to="Logs" method="_chat_bar_focus" binds= [ false ]]
[connection signal="text_entered" from="Logs/ResizablePanel/LineEdit" to="Logs" method="_text_submitted"]

View File

@ -1,5 +1,7 @@
extends Control
signal chat_message_sent(text)
onready var log_text = $ResizablePanel/RichTextLabel
onready var chat_bar = $ResizablePanel/LineEdit
@ -7,6 +9,8 @@ func _input(event: InputEvent) -> void:
if event is InputEventMouseButton:
if not chat_bar_focus:
chat_bar.release_focus()
if event.is_action_released("ui_chat") and chat_bar_focus == false:
chat_bar.grab_focus()
func add_line(line: String) -> void:
log_text.append_bbcode(line)
@ -18,3 +22,8 @@ func _chat_bar_status(editing: bool) -> void:
func _chat_bar_focus(entered: bool) -> void:
chat_bar_focus = entered
func _text_submitted(text):
emit_signal("chat_message_sent", text)
chat_bar.text = ""
chat_bar.release_focus()

View File

@ -1,76 +0,0 @@
[gd_scene load_steps=11 format=2]
[ext_resource path="res://Graphics/UI/iosevka-aile-regular.ttf" type="DynamicFontData" id=1]
[ext_resource path="res://Graphics/UI/iosevka-aile-italic.ttf" type="DynamicFontData" id=2]
[ext_resource path="res://Graphics/UI/iosevka-aile-bold.ttf" type="DynamicFontData" id=3]
[ext_resource path="res://Graphics/UI/iosevka-aile-bolditalic.ttf" type="DynamicFontData" id=4]
[ext_resource path="res://Scenes/UI/Panels/Logs.gd" type="Script" id=5]
[ext_resource path="res://Scenes/UI/Widgets/ResizablePanel.tscn" type="PackedScene" id=6]
[sub_resource type="DynamicFont" id=1]
size = 14
use_mipmaps = true
font_data = ExtResource( 4 )
[sub_resource type="DynamicFont" id=2]
size = 14
use_mipmaps = true
font_data = ExtResource( 2 )
[sub_resource type="DynamicFont" id=3]
size = 14
use_mipmaps = true
font_data = ExtResource( 3 )
[sub_resource type="DynamicFont" id=4]
size = 14
use_mipmaps = true
font_data = ExtResource( 1 )
[node name="Logs" type="Control"]
anchor_right = 1.0
anchor_bottom = 1.0
script = ExtResource( 5 )
__meta__ = {
"_edit_use_anchors_": false
}
[node name="ResizablePanel" parent="." instance=ExtResource( 6 )]
[node name="RichTextLabel" type="RichTextLabel" parent="ResizablePanel"]
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = 10.0
margin_top = 40.0
margin_right = -10.0
margin_bottom = -40.0
focus_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
custom_fonts/bold_italics_font = SubResource( 1 )
custom_fonts/italics_font = SubResource( 2 )
custom_fonts/bold_font = SubResource( 3 )
custom_fonts/normal_font = SubResource( 4 )
bbcode_enabled = true
selection_enabled = true
__meta__ = {
"_edit_use_anchors_": false
}
[node name="LineEdit" type="LineEdit" parent="ResizablePanel"]
anchor_top = 1.0
anchor_right = 1.0
anchor_bottom = 1.0
margin_left = 10.0
margin_top = -30.0
margin_right = -10.0
focus_mode = 1
caret_blink = true
caret_blink_speed = 0.5
__meta__ = {
"_edit_use_anchors_": false
}
[connection signal="focus_entered" from="ResizablePanel/LineEdit" to="." method="_chat_bar_status" binds= [ true ]]
[connection signal="focus_exited" from="ResizablePanel/LineEdit" to="." method="_chat_bar_status" binds= [ false ]]
[connection signal="mouse_entered" from="ResizablePanel/LineEdit" to="." method="_chat_bar_focus" binds= [ true ]]
[connection signal="mouse_exited" from="ResizablePanel/LineEdit" to="." method="_chat_bar_focus" binds= [ false ]]

View File

@ -1,6 +1,5 @@
extends WindowDialog
func _physics_process(delta):
func _physics_process(_delta):
if not visible:
return
multiplayer

View File

@ -6,6 +6,7 @@ export var bgzoom = 50
const BORDER_WIDTH = 4
const BORDER_LENGTH = 30
const RADAR_EFFECT_DELAY = 1
const HALF_BORDER = BORDER_LENGTH/2
export(Texture) var background
export(Font) var font
@ -87,13 +88,13 @@ func draw_target(viewport: Rect2, position: Vector2, color: Color):
var relative_pos = position - viewport.position
var clamped = Vector2(clamp(relative_pos.x, 0, viewport.size.x), clamp(relative_pos.y, 0, viewport.size.y))
if relative_pos.x < 0:
draw_line(Vector2(0, clamped.y-BORDER_LENGTH/2), Vector2(0, clamped.y+BORDER_LENGTH/2), color, BORDER_WIDTH)
draw_line(Vector2(0, clamped.y-HALF_BORDER), Vector2(0, clamped.y+HALF_BORDER), color, BORDER_WIDTH)
elif relative_pos.x > viewport.size.x:
draw_line(Vector2(viewport.size.x, clamped.y-BORDER_LENGTH/2), Vector2(viewport.size.x, clamped.y+BORDER_LENGTH/2), color, BORDER_WIDTH)
draw_line(Vector2(viewport.size.x, clamped.y-HALF_BORDER), Vector2(viewport.size.x, clamped.y+HALF_BORDER), color, BORDER_WIDTH)
if relative_pos.y < 0:
draw_line(Vector2(clamped.x-BORDER_LENGTH/2, 0), Vector2(clamped.x+BORDER_LENGTH/2, 0), color, BORDER_WIDTH)
draw_line(Vector2(clamped.x-HALF_BORDER, 0), Vector2(clamped.x+HALF_BORDER, 0), color, BORDER_WIDTH)
elif relative_pos.y > viewport.size.y:
draw_line(Vector2(clamped.x-BORDER_LENGTH/2, viewport.size.y), Vector2(clamped.x+BORDER_LENGTH/2, viewport.size.y), color, BORDER_WIDTH)
draw_line(Vector2(clamped.x-HALF_BORDER, viewport.size.y), Vector2(clamped.x+HALF_BORDER, viewport.size.y), color, BORDER_WIDTH)
func _input(event):
if event is InputEventMouseButton:

View File

@ -43,7 +43,7 @@ application/trademarks=""
[preset.1]
name="GOTM"
name="HTML5"
platform="HTML5"
runnable=true
custom_features=""

View File

@ -1,117 +0,0 @@
# MIT License
#
# Copyright (c) 2020-2020 Macaroni Studios AB
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
extends Node
#warnings-disable
# Official GDScript API for games on gotm.io
# This plugin serves as a polyfill while developing against the API locally.
# The 'real' API calls are only available when running the game live on gotm.io.
# Running the game in the web player (gotm.io/web-player) also counts as live.
# Add this script as a global autoload. Make sure the global autoload is named
# "Gotm". It must be named "Gotm" for it to work.
##############################################################
# SIGNALS
##############################################################
# You connected or disconnected from a lobby. Access it at 'Gotm.lobby'
signal lobby_changed()
# Files were drag'n'dropped into the screen.
# The 'files' argument is an array of 'GotmFile'.
signal files_dropped(files, screen)
##############################################################
# PROPERTIES
##############################################################
# These are all read only.
# Player information.
var user: GotmUser = GotmUser.new()
# Current lobby you are in.
# Is null when not in a lobby.
var lobby: GotmLobby = null
##############################################################
# METHODS
##############################################################
# The API is live when the game runs on gotm.io.
# Running the game in the web player (gotm.io/web-player) also counts as live.
func is_live() -> bool:
return false
# Create a new lobby and join it.
#
# If 'show_invitation' is true, show an invitation link in a popup.
#
# By default, the lobby is hidden and is only accessible directly through
# its 'invite_link'.
# Set 'lobby.hidden' to false to make it fetchable with 'GotmLobbyFetch'.
#
# Returns the hosted lobby (also accessible at 'Gotm.lobby').
static func host_lobby(show_invitation: bool = true) -> GotmLobby:
return _GotmImpl._host_lobby(GotmLobby.new())
# Play an audio snippet with 'message' as a synthesized voice.
# 'language' is in BCP 47 format (e.g. "en-US" for american english).
# If specified language is not available "en-US" is used.
# Return true if playback succeeded.
func text_to_speech(message: String, language: String = "en-US") -> bool:
return true # pretend it worked
# Asynchronously open up the browser's file picker.
#
# If 'types' is specified, limit the file picker to files with matching file
# types (https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file#Unique_file_type_specifiers).
# If 'only_one' is true, only allow the user to pick one file.
#
# If a picking-session is already in progress, an empty
# array is asynchronously returned.
#
# Asynchronously return an array of 'GotmFile'.
# Use 'yield(pick_files(), "completed")' to retrieve the return value.
func pick_files(types: Array = Array(), only_one: bool = false) -> Array:
yield(get_tree().create_timer(0.25), "timeout")
return []
##############################################################
# PRIVATE
##############################################################
func _ready() -> void:
_GotmImpl._initialize(GotmLobby, GotmUser)
func _process(delta) -> void:
_GotmImpl._process()
var _impl: Dictionary = {}

View File

@ -1,65 +0,0 @@
# MIT License
#
# Copyright (c) 2020-2020 Macaroni Studios AB
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
class_name GotmDebug
#warnings-disable
# Helper library for testing against the API locally, as if it would be live.
#
# These functions do not make real API calls. They fake operations and
# trigger relevant signals as if they happened live.
#
# These functions do nothing when the game is running live on gotm.io.
# Running the game in the web player (gotm.io/web-player) also counts as live.
# Host a lobby without joining it.
# Note that the lobby is hidden by default and not fetchable with
# 'GotmLobbyFetch'. To make it fetchable, set 'hidden' to false.
# The lobby is only fetchable and joinable in this game process.
# Returns added lobby.
static func add_lobby() -> GotmLobby:
return _GotmDebugImpl._add_lobby(GotmLobby.new())
# Remove a lobby created with 'add_lobby', as if its host (you) disconnected from it.
# Triggers 'lobby_changed' if you are in that lobby.
static func remove_lobby(lobby: GotmLobby) -> void:
_GotmDebugImpl._remove_lobby(lobby)
# Remove all lobbies.
static func clear_lobbies() -> void:
_GotmDebugImpl._clear_lobbies()
# Add yourself to the lobby, without joining it.
# Triggers 'peer_joined' if you are in that lobby.
# Returns joined peer.
static func add_lobby_peer(lobby: GotmLobby) -> GotmUser:
return _GotmDebugImpl._add_lobby_player(lobby, GotmUser.new())
# Remove a peer created with 'add_lobby_peer' from the lobby, as if the peer (you) disconnected
# from the lobby.
# Triggers 'peer_left' if you are in that lobby.
static func remove_lobby_peer(lobby: GotmLobby, peer: GotmUser) -> void:
_GotmDebugImpl._remove_lobby_player(lobby, peer)

View File

@ -1,50 +0,0 @@
# MIT License
#
# Copyright (c) 2020-2020 Macaroni Studios AB
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
class_name GotmFile
#warnings-disable
# A simple in-memory file descriptor used by 'Gotm.pick_files' and
# 'Gotm.files_dropped'.
##############################################################
# PROPERTIES
##############################################################
# File name.
var name: String
# File data.
var data: PoolByteArray
# Last time the file was modified in unix time (seconds since epoch).
var modified_time: int
##############################################################
# METHODS
##############################################################
# Save the file to the browser's download folder.
func download() -> void:
pass

View File

@ -1,155 +0,0 @@
# MIT License
#
# Copyright (c) 2020-2020 Macaroni Studios AB
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
class_name GotmLobby
#warnings-disable
# A lobby is a way of connecting players with eachother as if they
# were on the same local network.
#
# Lobbies can be joined either directly through an 'invite_link', or by
# joining lobbies fetched with the 'GotmLobbyFetch' class.
##############################################################
# SIGNALS
##############################################################
# Peer joined the lobby.
# 'peer_user' is a 'GotmUser' instance.
# This is only emitted if you are in this lobby.
signal peer_joined(peer_user)
# Peer left the lobby.
# 'peer_user' is a 'GotmUser' instance.
# This is only emitted if you are in this lobby.
signal peer_left(peer_user)
##############################################################
# READ-ONLY PROPERTIES
##############################################################
# Globally unique identifier.
var id: String
# Other peers in the lobby with addresses.
# Is an array of 'GotmUser'.
var peers: Array = []
# You with address.
var me: GotmUser = GotmUser.new()
# Host user with address.
var host: GotmUser = GotmUser.new()
# Peers can join the lobby directly through this link.
var invite_link: String
##############################################################
# WRITABLE PROPERTIES
##############################################################
# Note that only the host can write to these properties.
# Name that is searchable using 'GotmLobbyFetch'
# Names longer than 64 characters are truncated.
var name: String = ""
# Prevent the lobby from showing up in fetches?
# Peers may still join directly through 'invite_link'
var hidden: bool = true
# Prevent new peers from joining?
# Also prevents the lobby from showing up in fetches.
var locked: bool = false
##############################################################
# METHODS
##############################################################
# Asynchronously join this lobby after leaving current lobby.
#
# Use 'var success = yield(lobby.join(), "completed")' to wait for the call to complete
# and retrieve the return value.
#
# Sets 'Gotm.lobby' to the joined lobby if successful.
#
# Asyncronously returns true if successful, else false.
func join() -> bool:
return yield(_GotmImpl._join_lobby(self), "completed")
# Leave this lobby.
func leave() -> void:
_GotmImpl._leave_lobby(self)
# Am I the host of this lobby?
func is_host() -> bool:
return _GotmImpl._is_lobby_host(self)
# Get a custom property.
func get_property(name: String):
return _GotmImpl._get_lobby_property(self, name)
################################
# Host-only methods
################################
# Kick peer from this lobby.
# Returns true if successful, else false.
func kick(peer: GotmUser) -> bool:
return _GotmImpl._kick_lobby_peer(self, peer)
# Store up to 10 of your own custom properties in the lobby.
# These are visible to other peers when fetching lobbies.
# Only properties of types String, int, float or bool are allowed.
# Integers are converted to floats.
# Strings longer than 64 characters are truncated.
# Setting 'value' to null removes the property.
func set_property(name: String, value) -> void:
_GotmImpl._set_lobby_property(self, name, value)
# Make this lobby filterable by a custom property.
# Filtering is done when fetching lobbies with 'GotmLobbyFetch'.
# Up to 3 properties can be set as filterable at once.
func set_filterable(property_name: String, filterable: bool = true) -> void:
_GotmImpl._set_lobby_filterable(self, property_name, filterable)
# Make this lobby sortable by a custom property.
# Sorting is done when fetching lobbies with 'GotmLobbyFetch'.
# Up to 3 properties can be set as sortable at once.
func set_sortable(property_name: String, sortable: bool = true) -> void:
_GotmImpl._set_lobby_sortable(self, property_name, sortable)
################################
# PRIVATE
################################
var _impl: Dictionary = {}

View File

@ -1,122 +0,0 @@
# MIT License
#
# Copyright (c) 2020-2020 Macaroni Studios AB
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
class_name GotmLobbyFetch
#warnings-disable
# Used for fetching non-hidden and non-locked lobbies.
##############################################################
# PROPERTIES
##############################################################
################
# Filter options
################
# If not empty, fetch lobbies whose 'Lobby.name' contains 'name'.
var filter_name: String = ""
# If not empty, fetch lobbies whose filterable custom properties
# matches those in 'filter_properties'.
#
# For example, setting 'filter_properties.difficulty = 2' will
# only fetch lobbies that have been set up with both 'lobby.set_property("difficulty", 2)'
# and 'lobby.set_filterable("difficulty", true)'.
#
# If your lobby has multiple filterable props, you must provide every filterable
# prop in 'filter_properties'. Setting a prop's value to 'null' will match any
# value of that prop.
var filter_properties: Dictionary = {}
################
# Sort options
################
# If not empty, sort by a sortable custom property.
#
# For example, setting 'sort_property = "difficulty"' will
# only fetch lobbies that have been set up with both 'lobby.set_property("difficulty", some_value)'
# and 'lobby.set_sortable("difficulty", true)'.
#
# If your lobby has a sortable prop, you must always provide a 'sort_property'.
var sort_property: String = ""
# Sort results in ascending order?
var sort_ascending: bool = false
# If not null, fetch lobbies whose sort property's value is equal to or greater than 'sort_min'.