extends Node var nakama_client: NakamaClient var nakama_session: NakamaSession var nakama_socket: NakamaSocket const SERVER_WIDTH = 90.0 const SERVER_HEIGHT = 160.0 var predicted_tick = 0 var delta_counter = 0 var bullet_lerp_factor := 0.0 var bullets = [] var current_match_id = "" func _ready() -> void: print("Attempting auth.") await attempt_auth() print("Attempting to create debug match.") await create_and_join_debug_match() nakama_socket.received_match_state.connect(self._on_match_state) func _process(delta: float) -> void: if current_match_id == "": return predict_tick_and_broadcast(delta) for bullet in bullets: var prev_pos = bullet.get_current_pos(predicted_tick) var next_pos = bullet.get_current_pos(predicted_tick + 1) var interpolated_pos = prev_pos.lerp(next_pos, bullet_lerp_factor) bullet.position = world_to_screen(interpolated_pos) #var screen_size = get_viewport().size #bullets = bullets.filter(func(bullet): # return bullet.position.x >= 0 and bullet.position.x <= screen_size.x and \ # bullet.position.y >= 0 and bullet.position.y <= screen_size.y #) func _on_match_state(p_state : NakamaRTAPI.MatchData): match p_state.op_code: 2: # Server state update var data = JSON.parse_string(p_state.data) var bullet = DanmakuBullet.new() bullet.setup_bullet( int(data["class"]), int(data["tick"]), data["x"], data["y"], data["vel_x"], data["vel_y"]) bullet.position = world_to_screen(bullet.get_current_pos(int(data["tick"]))) bullet.texture = load("res://test-bullet.png") add_child(bullet) bullets.append(bullet) #delta_counter = 0 #predicted_tick = int(data["tick"]) func attempt_auth() -> void: nakama_client = Nakama.create_client("defaultkey", "127.0.0.1", 7350, "http") nakama_session = await nakama_client.authenticate_device_async(OS.get_unique_id()) nakama_socket = Nakama.create_socket_from(nakama_client) var connected: NakamaAsyncResult = await nakama_socket.connect_async(nakama_session) if connected.is_exception(): print("An error occured when creating nakama socket: %s" % connected) return print("Oh baby we're ready.") func create_and_join_debug_match() -> void: var response: NakamaAPI.ApiRpc = await nakama_client.rpc_async(nakama_session, "manual_force_create_br_match_rpc") if response.is_exception(): print("An error occurred when calling manual_force_create_br_match_rpc: %s" % response) return var debug_br_match: NakamaRTAPI.Match = await nakama_socket.join_match_async(response.payload) if debug_br_match.is_exception(): print("An error occurred when joining debug BR match: %s" % response) return else: current_match_id = response.payload func world_to_screen(server_pos: Vector2) -> Vector2: var screen_size = get_viewport().size var scale_x = screen_size.x / SERVER_WIDTH var scale_y = screen_size.y / SERVER_HEIGHT var client_x = server_pos.x * scale_x var client_y = server_pos.y * scale_y return Vector2(client_x, client_y) func screen_to_world(client_pos: Vector2) -> Vector2: var screen_size = get_viewport().size var scale_x = SERVER_WIDTH / screen_size.x var scale_y = SERVER_HEIGHT / screen_size.y var server_x = client_pos.x * scale_x var server_y = client_pos.y * scale_y return Vector2(server_x, server_y) func predict_tick_and_broadcast(delta): delta_counter += delta # New tick, broadcast player inputs if delta_counter >= 0.05: predicted_tick += 1 delta_counter = 0 var position = screen_to_world(get_node("../Player").position) var json_string = JSON.stringify({"x": position.x, "y": position.y}) nakama_socket.send_match_state_async(current_match_id, 0, json_string) bullet_lerp_factor = delta_counter / 0.05