diff --git a/Actors/Player/Player.gd b/Actors/Player/Player.gd index bd881b7..9e6703a 100644 --- a/Actors/Player/Player.gd +++ b/Actors/Player/Player.gd @@ -11,7 +11,9 @@ var grip = 1.0 var stamina = MAX_STAMINA var speed_boost = 0 +onready var scene = $"/root/scene" onready var world = $"/root/scene/world" +onready var camera = $Camera export var is_controlled = false setget set_is_controlled diff --git a/Actors/Systems/Electricity/PowerNetwork.gd b/Actors/Systems/Electricity/PowerNetwork.gd index da1bf0e..0343cc3 100644 --- a/Actors/Systems/Electricity/PowerNetwork.gd +++ b/Actors/Systems/Electricity/PowerNetwork.gd @@ -78,6 +78,7 @@ func _physics_process(_delta: float) -> void: sink.available = available_supply # Check how much we actually need to drain from sources var remaining_drain = total_source - available_supply - for source in sources: - var source_load = source.power_source / total_source * remaining_drain - source.power_load = source_load + if remaining_drain > 0: + for source in sources: + var source_load = source.power_source / total_source * remaining_drain + source.power_load = source_load diff --git a/Graphics/UI/Background.shader b/Graphics/UI/Background.shader index ca9c79c..b8eaaf2 100644 --- a/Graphics/UI/Background.shader +++ b/Graphics/UI/Background.shader @@ -23,7 +23,7 @@ void fragment() { vec2 uv = FRAGCOORD.xy * SCREEN_PIXEL_SIZE - 0.5; uv.y *= SCREEN_PIXEL_SIZE.x/SCREEN_PIXEL_SIZE.y; - vec3 dir = vec3(uv*zoom, 1.); + vec3 dir = vec3(uv*(zoom+sin(TIME*0.01)*0.4), 1.); float time = TIME*speed+.25; float a1=.5+TIME*rotx; diff --git a/Graphics/UI/logo-temp-pixel.png b/Graphics/UI/logo-temp-pixel.png new file mode 100644 index 0000000..6f4fb6a Binary files /dev/null and b/Graphics/UI/logo-temp-pixel.png differ diff --git a/Graphics/UI/logo-temp-pixel.png.import b/Graphics/UI/logo-temp-pixel.png.import new file mode 100644 index 0000000..a80bef4 --- /dev/null +++ b/Graphics/UI/logo-temp-pixel.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="StreamTexture" +path="res://.import/logo-temp-pixel.png-7960fa53393f7cfe8d3a7306254ddecf.stex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://Graphics/UI/logo-temp-pixel.png" +dest_files=[ "res://.import/logo-temp-pixel.png-7960fa53393f7cfe8d3a7306254ddecf.stex" ] + +[params] + +compress/mode=0 +compress/lossy_quality=0.7 +compress/hdr_mode=0 +compress/bptc_ldr=0 +compress/normal_map=0 +flags/repeat=0 +flags/filter=false +flags/mipmaps=false +flags/anisotropic=false +flags/srgb=2 +process/fix_alpha_border=true +process/premult_alpha=false +process/HDR_as_SRGB=false +process/invert_color=false +stream=false +size_limit=0 +detect_3d=true +svg/scale=1.0 diff --git a/Graphics/logo-temp.afdesign b/Graphics/logo-temp.afdesign index 54fb89d..d2eae6a 100644 Binary files a/Graphics/logo-temp.afdesign and b/Graphics/logo-temp.afdesign differ diff --git a/Scenes/Game.tscn b/Scenes/Game.tscn index 6646141..1521c3c 100644 --- a/Scenes/Game.tscn +++ b/Scenes/Game.tscn @@ -7,6 +7,8 @@ [node name="scene" type="Node"] script = ExtResource( 5 ) +[node name="systems" type="Node" parent="."] + [node name="world" type="Node2D" parent="."] scale = Vector2( 2, 2 ) script = ExtResource( 4 ) @@ -17,6 +19,3 @@ mapToLoad = 1 [node name="CanvasLayer" type="CanvasLayer" parent="."] [node name="ui" parent="CanvasLayer" instance=ExtResource( 3 )] -mouse_filter = 2 - -[node name="systems" type="Node" parent="."] diff --git a/Scenes/Global/Multiplayer.gd b/Scenes/Global/Multiplayer.gd index 8c7340c..0ef6f58 100644 --- a/Scenes/Global/Multiplayer.gd +++ b/Scenes/Global/Multiplayer.gd @@ -1,43 +1,108 @@ extends Node +signal ms_updated(action, data) +signal left() + +# Hosting info const SERVER_PORT = 5513 const MAX_PLAYERS = 30 +var port = SERVER_PORT + +# Master server data +const MASTER_SERVER_ADDR = "fgms.zyg.ovh" +const MASTER_SERVER_UDP_PORT = 9434 +const MS_GAME_CODE = "odyssey-0-a1" + +# Master server entry +var ms_active = false +var ms_key = "" +var server_name = "" export var player_name = "" + var player_info = {} func _ready(): player_name = "tider-" + str(randi() % 1000) + +func bind_events(): get_tree().connect("network_peer_connected", self, "_player_connected") get_tree().connect("network_peer_disconnected", self, "_player_disconnected") get_tree().connect("connected_to_server", self, "_connected_ok") get_tree().connect("connection_failed", self, "_connected_fail") get_tree().connect("server_disconnected", self, "_server_disconnected") +func punch_nat(): + var socketUDP = PacketPeerUDP.new() + if socketUDP.listen(SERVER_PORT) != OK: + push_error("error listening on port: " + str(SERVER_PORT)) + socketUDP.set_dest_address(MASTER_SERVER_ADDR, MASTER_SERVER_UDP_PORT) + socketUDP.put_packet("hi server!".to_ascii()) + # Poll for answer from server, since godot doesn't have events for UDP packets (ノへ ̄、) + var failed = 0 + while failed < 5: + yield(get_tree().create_timer(.3), "timeout") + if socketUDP.get_available_packet_count() < 1: + failed += 1 + print("no reply (attempt #", failed, ")") + continue + port = socketUDP.get_var(false) + print("Received ", port) + break + socketUDP.close() + +func discover_upnp(): + var upnp = UPNP.new() + upnp.discover(2000, 2, "InternetGatewayDevice") + return upnp.add_port_mapping(SERVER_PORT) + func host(): + 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") + + bind_events() var peer = NetworkedMultiplayerENet.new() - peer.create_server(SERVER_PORT, MAX_PLAYERS) - get_tree().set_network_peer(peer) + var server_res = peer.create_server(port, MAX_PLAYERS) + if server_res != OK: + match server_res: + ERR_CANT_CREATE: + push_error("Can't create server") + ERR_ALREADY_IN_USE: + push_error("Already in use") + return + get_tree().network_peer = peer print("Hosting") + server_name = player_name + "'s server" player_info[1] = { name=player_name } - #mapLoader.map.spawn_player(peer.get_unique_id()) + + get_tree().change_scene("res://Scenes/Game.tscn") + + # Add to master server + create_ms_entry() func join(addr: String): + bind_events() var peer = NetworkedMultiplayerENet.new() peer.create_client(addr, SERVER_PORT) get_tree().network_peer = peer - print("Connecting to", addr) + print("Connecting to ", addr) func leave(): var peer = get_tree().network_peer if get_tree().is_network_server(): - #TODO Do something if server - pass + # Tell MS we're leaving + if ms_active: + _ms_request("remove", { "key": ms_key }) + yield(self, "ms_updated") elif peer != null: #TODO Send leave message pass get_tree().network_peer = null - + emit_signal("left") func _player_connected(id): rpc_id(id, "register_player", player_name) if get_tree().is_network_server(): @@ -55,7 +120,7 @@ func _server_disconnected(): print("Disconnected from server") func _connected_fail(): - print("Connection failed") + push_warning("Connection failed") remote func register_player(username: String): var id = get_tree().get_rpc_sender_id() @@ -68,3 +133,57 @@ remote func spawn_players(players): #mapLoader.map.spawn_player(player_id) # Spawn myself as well #mapLoader.map.rpc("spawn_player", get_tree().network_peer.get_unique_id()) + +func _ms_request(endpoint: String, data): + var http_request = HTTPRequest.new() + add_child(http_request) + http_request.connect("request_completed", self, "_ms_response", [endpoint]) + print_debug("Telling ms to " + endpoint) + var error = http_request.request( + "https://" + MASTER_SERVER_ADDR + "/" + endpoint, + ["Content-Type: application/json"], + true, HTTPClient.METHOD_POST, JSON.print(data)) + if error != OK: + push_error("An error occurred in the HTTP request.") + +func get_game_data(): + return { + "name": server_name, + "port": port, + "max_players": MAX_PLAYERS, + "players": player_info.size() + } + +func create_ms_entry(): + _ms_request("new", { + "game_id": MS_GAME_CODE, + "data": get_game_data() + }) + update_ms_entry() + +func update_ms_entry(): + if ms_active: + _ms_request("update", { + "key": ms_key, + "data": get_game_data() + }) + yield(get_tree().create_timer(20), "timeout") + +func _ms_response(_result: int, response_code: int, _headers: PoolStringArray, body: PoolByteArray, action: String): + print_debug("MS said " + str(response_code)) + if response_code > 299: + push_error("ms action \"" + action + "\" returned error: " + str(response_code) + " - " + body.get_string_from_utf8()) + return + var json = JSON.parse(body.get_string_from_utf8()) + match action: + "new": + if json.result.ok: + ms_active = true + ms_key = json.result.key + emit_signal("ms_updated", action, json.result) + +func _notification(what): + # Are we quittin son? + if what == MainLoop.NOTIFICATION_WM_QUIT_REQUEST: + leave() + yield(self, "left") diff --git a/Scenes/Global/Music.tscn b/Scenes/Global/Music.tscn index 266b08d..fbed83c 100644 --- a/Scenes/Global/Music.tscn +++ b/Scenes/Global/Music.tscn @@ -2,12 +2,7 @@ [ext_resource path="res://Sounds/BGM/Bluemillenium_-_Je_suis_un_Phoenix_1.ogg" type="AudioStream" id=1] -[node name="Music" type="Control"] -anchor_right = 1.0 -anchor_bottom = 1.0 -__meta__ = { -"_edit_use_anchors_": false -} +[node name="Music" type="Node"] [node name="BGM" type="AudioStreamPlayer" parent="."] stream = ExtResource( 1 ) diff --git a/Scenes/Maps/odyssey.tscn b/Scenes/Maps/odyssey.tscn index 2a2d001..ebbd860 100644 --- a/Scenes/Maps/odyssey.tscn +++ b/Scenes/Maps/odyssey.tscn @@ -152,6 +152,7 @@ interlockTargetPath = NodePath("../AirlockExt3") [node name="ControlComp" parent="objects" instance=ExtResource( 6 )] position = Vector2( 576, 256 ) direction = 0 +computer_type = 0 [node name="CommsComp" parent="objects" instance=ExtResource( 6 )] position = Vector2( 576, 224 ) diff --git a/Scenes/Menu.gd b/Scenes/Menu.gd index 71fde41..81f7dee 100644 --- a/Scenes/Menu.gd +++ b/Scenes/Menu.gd @@ -18,7 +18,7 @@ func _process(delta): if delta > downThreshold: print("GPU is taking too much (", delta, "s < ", downThreshold, "s), adjusting shader scale") set_scale(scale+1) - elif delta < upThreshold and scale > 1: + elif delta < upThreshold and scale > 2: print("GPU is taking it easy (", delta, "s < ", upThreshold, "s), adjusting shader scale") set_scale(scale-1) @@ -30,3 +30,13 @@ func set_scale(val): func _on_resized(): $Viewport.size = rect_size / scale $Background.update() + +func _host_pressed(): + $"/root/Music/BGM".stop() + $"/root/Multiplayer".host() + +func _join_pressed(): + pass + +func _server_addr_changed(new_text: String): + $CenterContainer/PanelContainer/HBoxContainer/JoinButton.disabled = new_text.length() < 1 diff --git a/Scenes/Menu.tscn b/Scenes/Menu.tscn index a2ff025..a295d58 100644 --- a/Scenes/Menu.tscn +++ b/Scenes/Menu.tscn @@ -1,12 +1,25 @@ -[gd_scene load_steps=6 format=2] +[gd_scene load_steps=10 format=2] [ext_resource path="res://Scenes/Menu.gd" type="Script" id=1] [ext_resource path="res://Graphics/UI/Background.shader" type="Shader" id=2] -[ext_resource path="res://Graphics/UI/logo-temp.png" type="Texture" id=3] +[ext_resource path="res://Graphics/UI/logo-temp-pixel.png" type="Texture" id=3] +[ext_resource path="res://Graphics/UI/ui_theme.tres" type="Theme" id=4] -[sub_resource type="ViewportTexture" id=3] +[sub_resource type="ViewportTexture" id=1] viewport_path = NodePath("Viewport") +[sub_resource type="Shader" id=2] +code = "shader_type canvas_item; + +void fragment() { + vec4 tex = texture(TEXTURE, UV); + COLOR = vec4(tex.rgb * 0., tex.a * 0.5); +}" +custom_defines = "" + +[sub_resource type="ShaderMaterial" id=3] +shader = SubResource( 2 ) + [sub_resource type="ShaderMaterial" id=4] shader = ExtResource( 2 ) shader_param/iterations = 17 @@ -23,6 +36,22 @@ shader_param/saturation = 0.85 shader_param/rotx = 0.0 shader_param/roty = 0.001 +[sub_resource type="StyleBoxFlat" id=5] +content_margin_left = 16.0 +content_margin_right = 16.0 +content_margin_top = 20.0 +content_margin_bottom = 20.0 +bg_color = Color( 0.133333, 0.12549, 0.203922, 0.784314 ) +border_width_left = 4 +border_width_top = 4 +border_width_right = 4 +border_width_bottom = 4 +border_color = Color( 0.27301, 0.417506, 0.984375, 0.392157 ) +corner_radius_top_left = 4 +corner_radius_top_right = 4 +corner_radius_bottom_right = 4 +corner_radius_bottom_left = 4 + [node name="Control" type="Control"] anchor_right = 1.0 anchor_bottom = 1.0 @@ -34,23 +63,42 @@ __meta__ = { [node name="Background" type="TextureRect" parent="."] anchor_right = 1.0 anchor_bottom = 1.0 -texture = SubResource( 3 ) +texture = SubResource( 1 ) stretch_mode = 7 __meta__ = { "_edit_use_anchors_": false } +[node name="logo-temp2" type="TextureRect" parent="."] +material = SubResource( 3 ) +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +margin_left = -248.771 +margin_top = -295.282 +margin_right = -8.77124 +margin_bottom = -115.282 +grow_horizontal = 2 +grow_vertical = 2 +rect_scale = Vector2( 2, 2 ) +texture = ExtResource( 3 ) +__meta__ = { +"_edit_use_anchors_": false +} + [node name="logo-temp" type="TextureRect" parent="."] anchor_left = 0.5 anchor_top = 0.5 anchor_right = 0.5 anchor_bottom = 0.5 -margin_left = -250.0 -margin_top = -293.953 -margin_right = 250.0 -margin_bottom = 82.0471 +margin_left = -250.58 +margin_top = -296.523 +margin_right = -10.5796 +margin_bottom = -116.523 grow_horizontal = 2 grow_vertical = 2 +rect_scale = Vector2( 2, 2 ) texture = ExtResource( 3 ) __meta__ = { "_edit_use_anchors_": false @@ -63,4 +111,66 @@ size = Vector2( 300, 300 ) material = SubResource( 4 ) anchor_right = 1.0 anchor_bottom = 1.0 + +[node name="CenterContainer" type="CenterContainer" parent="."] +anchor_top = 1.0 +anchor_right = 1.0 +anchor_bottom = 1.0 +margin_left = 100.0 +margin_top = -300.0 +margin_right = -100.0 +margin_bottom = -50.0 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="PanelContainer" type="PanelContainer" parent="CenterContainer"] +margin_left = 390.0 +margin_top = 43.0 +margin_right = 690.0 +margin_bottom = 207.0 +rect_min_size = Vector2( 300, 0 ) +custom_styles/panel = SubResource( 5 ) + +[node name="HBoxContainer" type="VBoxContainer" parent="CenterContainer/PanelContainer"] +margin_left = 16.0 +margin_top = 20.0 +margin_right = 284.0 +margin_bottom = 144.0 +custom_constants/separation = 10 + +[node name="HostButton" type="Button" parent="CenterContainer/PanelContainer/HBoxContainer"] +margin_right = 268.0 +margin_bottom = 24.0 +theme = ExtResource( 4 ) +text = "Start a new game" + +[node name="Label" type="Label" parent="CenterContainer/PanelContainer/HBoxContainer"] +margin_top = 34.0 +margin_right = 268.0 +margin_bottom = 52.0 +theme = ExtResource( 4 ) +text = "or" +align = 1 +__meta__ = { +"_edit_use_anchors_": false +} + +[node name="ServerAddr" type="LineEdit" parent="CenterContainer/PanelContainer/HBoxContainer"] +margin_top = 62.0 +margin_right = 268.0 +margin_bottom = 90.0 +theme = ExtResource( 4 ) +placeholder_text = "Server address or URL" + +[node name="JoinButton" type="Button" parent="CenterContainer/PanelContainer/HBoxContainer"] +margin_top = 100.0 +margin_right = 268.0 +margin_bottom = 124.0 +theme = ExtResource( 4 ) +disabled = true +text = "Join an existing game" [connection signal="resized" from="." to="." method="_on_resized"] +[connection signal="pressed" from="CenterContainer/PanelContainer/HBoxContainer/HostButton" to="." method="_host_pressed"] +[connection signal="text_changed" from="CenterContainer/PanelContainer/HBoxContainer/ServerAddr" to="." method="_server_addr_changed"] +[connection signal="pressed" from="CenterContainer/PanelContainer/HBoxContainer/JoinButton" to="." method="_join_pressed"] diff --git a/Scenes/Rendering/MapTiles.gd b/Scenes/Rendering/MapTiles.gd index 6b8aae7..cf94833 100644 --- a/Scenes/Rendering/MapTiles.gd +++ b/Scenes/Rendering/MapTiles.gd @@ -2,6 +2,8 @@ extends TileMap class_name MapTiles +var transparentImage = preload("res://Graphics/transparent.png") + export(NodePath) var extended_tilemap_node export var occluders = ["Wall"] @@ -34,7 +36,7 @@ func convert_extended(): extended_tilemap.set_cell(x+1, y, extended_id) extended_tilemap.set_cell(x, y+1, extended_id) extended_tilemap.set_cell(x+1, y+1, extended_id) - set_cellv(cell, -1) + tile_set.tile_set_texture(id, transparentImage) extended_tilemap.update_bitmask_region() extended_tilemap.update_dirty_quadrants() diff --git a/Scenes/UI.tscn b/Scenes/UI.tscn index 92f1e94..f2a42c5 100644 --- a/Scenes/UI.tscn +++ b/Scenes/UI.tscn @@ -20,6 +20,7 @@ corner_radius_bottom_left = 4 [node name="ui" type="Control"] anchor_right = 1.0 anchor_bottom = 1.0 +mouse_filter = 2 size_flags_horizontal = 3 size_flags_vertical = 3 script = ExtResource( 2 ) @@ -83,10 +84,10 @@ margin_bottom = 20.0 text = "Preferences" [node name="ServerInfoPopup" type="WindowDialog" parent="."] -margin_left = 536.0 -margin_top = 272.0 -margin_right = 792.0 -margin_bottom = 440.0 +margin_left = -278.587 +margin_top = 58.4538 +margin_right = -22.587 +margin_bottom = 226.454 window_title = "Server info" resizable = true __meta__ = { diff --git a/export_presets.cfg b/export_presets.cfg index bb51b1c..ed23bfc 100644 --- a/export_presets.cfg +++ b/export_presets.cfg @@ -32,11 +32,11 @@ codesign/timestamp_server_url="" codesign/digest_algorithm=1 codesign/description="" codesign/custom_options=PoolStringArray( ) -application/icon="" -application/file_version="" -application/product_version="" +application/icon="res://icon.ico" +application/file_version="0.1.0" +application/product_version="0.1.0" application/company_name="" -application/product_name="" +application/product_name="NSS Odyssey" application/file_description="" application/copyright="" application/trademarks="" diff --git a/icon.ico b/icon.ico new file mode 100644 index 0000000..c193bca Binary files /dev/null and b/icon.ico differ diff --git a/icon.png b/icon.png index c98fbb6..353ee25 100755 Binary files a/icon.png and b/icon.png differ diff --git a/project.godot b/project.godot index fe0fab3..e43245f 100644 --- a/project.godot +++ b/project.godot @@ -128,7 +128,7 @@ _global_script_class_icons={ [application] -config/name="odyssey" +config/name="NSS Odyssey" run/main_scene="res://Scenes/Menu.tscn" boot_splash/image="res://Graphics/UI/splash.png" boot_splash/fullsize=false @@ -137,6 +137,11 @@ config/icon="res://icon.png" [autoload] Music="*res://Scenes/Global/Music.tscn" +Multiplayer="*res://Scenes/Global/Multiplayer.gd" + +[debug] + +settings/stdout/print_fps=true [display]