Updating location schema to tracker user territory and lock visibility

This commit is contained in:
hz
2026-05-18 13:59:33 -05:00
parent dd151c5af1
commit afeb9cf625
23 changed files with 590 additions and 38 deletions
@@ -1,15 +1,21 @@
extends Control
const SESSION_PATH := "user://auth_session.json"
const LOCATIONS_BASE_URL := "https://tloc.ranaze.com"
const HexGridView := preload("res://scenes/game/hex_grid_view.gd")
var coordinate_label: Label
var title_font: Font
var grid_view
var http_request: HTTPRequest
var visible_request: HTTPRequest
var session: Dictionary = {}
func _ready() -> void:
session = _load_session()
_build_ui()
_assign_home_location()
func _build_ui() -> void:
@@ -97,6 +103,14 @@ func _build_ui() -> void:
coordinate_label.add_theme_color_override("font_color", Color(0.72, 0.8, 0.78))
bottom_margin.add_child(coordinate_label)
http_request = HTTPRequest.new()
http_request.request_completed.connect(_on_home_request_completed)
add_child(http_request)
visible_request = HTTPRequest.new()
visible_request.request_completed.connect(_on_visible_request_completed)
add_child(visible_request)
func _on_tile_hovered(q: int, r: int, terrain: String) -> void:
if coordinate_label:
@@ -109,23 +123,110 @@ func _on_tile_selected(q: int, r: int, terrain: String) -> void:
func _session_name() -> String:
if not session.is_empty():
var session_username: String = str(session.get("username", "Signed in"))
var session_role: String = str(session.get("role", "USER"))
return "%s | %s" % [session_username, session_role]
return "Signed in"
func _load_session() -> Dictionary:
if get_tree().has_meta("auth_session"):
var current_session = get_tree().get_meta("auth_session")
if typeof(current_session) == TYPE_DICTIONARY:
var current_username: String = str(current_session.get("username", "Signed in"))
var current_role: String = str(current_session.get("role", "USER"))
return "%s | %s" % [current_username, current_role]
return current_session
var file := FileAccess.open(SESSION_PATH, FileAccess.READ)
if not file:
return "Signed in"
return {}
var parsed = JSON.parse_string(file.get_as_text())
if typeof(parsed) == TYPE_DICTIONARY:
var username: String = str(parsed.get("username", "Signed in"))
var role: String = str(parsed.get("role", "USER"))
return "%s | %s" % [username, role]
return "Signed in"
return parsed
return {}
func _assign_home_location() -> void:
var access_token: String = str(session.get("accessToken", ""))
if access_token.is_empty():
coordinate_label.text = "No auth token available. Home territory was not assigned."
return
coordinate_label.text = "Assigning home territory..."
var error: int = http_request.request(
LOCATIONS_BASE_URL + "/api/locations/home",
PackedStringArray([
"Content-Type: application/json",
"Authorization: Bearer %s" % access_token
]),
HTTPClient.METHOD_POST,
""
)
if error != OK:
coordinate_label.text = "Could not contact the locations service."
func _on_home_request_completed(result: int, response_code: int, _headers: PackedStringArray, body: PackedByteArray) -> void:
if result != HTTPRequest.RESULT_SUCCESS:
coordinate_label.text = "Locations service request failed."
return
var text: String = body.get_string_from_utf8()
if response_code < 200 or response_code >= 300:
coordinate_label.text = "Home assignment failed: %s" % text
return
var parsed = JSON.parse_string(text)
if typeof(parsed) != TYPE_DICTIONARY:
coordinate_label.text = "Locations service returned invalid home data."
return
var home: Dictionary = parsed
var q: int = int(home.get("q", 0))
var r: int = int(home.get("r", 0))
var terrain: String = str(home.get("terrain", "Command"))
grid_view.set_home_location(q, r)
coordinate_label.text = "Home territory assigned at q:%d r:%d | %s" % [q, r, terrain]
_load_visible_locations()
func _load_visible_locations() -> void:
var access_token: String = str(session.get("accessToken", ""))
if access_token.is_empty():
coordinate_label.text = "No auth token available. Visibility was not loaded."
return
var error: int = visible_request.request(
LOCATIONS_BASE_URL + "/api/locations/visible",
PackedStringArray([
"Authorization: Bearer %s" % access_token
]),
HTTPClient.METHOD_GET
)
if error != OK:
coordinate_label.text = "Could not request visible territory."
func _on_visible_request_completed(result: int, response_code: int, _headers: PackedStringArray, body: PackedByteArray) -> void:
if result != HTTPRequest.RESULT_SUCCESS:
coordinate_label.text = "Visible territory request failed."
return
var text: String = body.get_string_from_utf8()
if response_code < 200 or response_code >= 300:
coordinate_label.text = "Visible territory failed: %s" % text
return
var parsed = JSON.parse_string(text)
if typeof(parsed) != TYPE_ARRAY:
coordinate_label.text = "Locations service returned invalid visibility data."
return
var username: String = str(session.get("username", ""))
var visible_locations: Array = parsed
grid_view.set_visible_locations(visible_locations, username)
coordinate_label.text = "Visible territory loaded. Sight extends 3 hexes beyond controlled land."
func _panel_style(color: Color, border_color: Color, border_width: int, radius: int) -> StyleBoxFlat:
@@ -14,7 +14,10 @@ var drag_distance: float = 0.0
var last_mouse_position: Vector2 = Vector2.ZERO
var hovered_tile: Vector2i = Vector2i(9999, 9999)
var selected_tile: Vector2i = Vector2i(9999, 9999)
var home_tile: Vector2i = Vector2i(9999, 9999)
var tiles: Array[Dictionary] = []
var visible_tiles: Dictionary = {}
var owned_tiles: Dictionary = {}
func _ready() -> void:
@@ -26,19 +29,34 @@ func _ready() -> void:
func _build_tiles() -> void:
tiles.clear()
var radius: int = 7
for q in range(-radius, radius + 1):
var r_min: int = int(max(-radius, -q - radius))
var r_max: int = int(min(radius, -q + radius))
for r in range(r_min, r_max + 1):
var height: float = _tile_height(q, r)
tiles.append({
"q": q,
"r": r,
"height": height,
"terrain": _terrain_name(q, r, height),
"color": _terrain_color(q, r, height)
})
_build_tiles_around(0, 0, 7)
func _build_tiles_around(center_q: int, center_r: int, radius: int) -> void:
tiles.clear()
for dq in range(-radius, radius + 1):
var min_dr: int = int(max(-radius, -dq - radius))
var max_dr: int = int(min(radius, -dq + radius))
for dr in range(min_dr, max_dr + 1):
_add_or_update_tile(center_q + dq, center_r + dr)
func _add_or_update_tile(q: int, r: int, terrain_override: String = "") -> void:
var height: float = _tile_height(q, r)
var terrain: String = terrain_override if not terrain_override.is_empty() else _terrain_name(q, r, height)
var existing: Dictionary = _tile_data(q, r)
if not existing.is_empty():
existing["terrain"] = terrain
existing["color"] = _terrain_color_for_name(terrain, q, r, height)
return
tiles.append({
"q": q,
"r": r,
"height": height,
"terrain": terrain,
"color": _terrain_color_for_name(terrain, q, r, height)
})
func _gui_input(event: InputEvent) -> void:
@@ -106,12 +124,22 @@ func _draw_tile(tile: Dictionary) -> void:
var coord: Vector2i = Vector2i(q, r)
var is_hovered: bool = coord == hovered_tile
var is_selected: bool = coord == selected_tile
var key: String = _tile_key(q, r)
var is_visible: bool = visible_tiles.has(key)
var is_owned: bool = owned_tiles.has(key)
var side_points: PackedVector2Array = PackedVector2Array([points[2], points[3], points[4], points[4] + Vector2(0, 14), points[3] + Vector2(0, 14), points[2] + Vector2(0, 14)])
draw_colored_polygon(side_points, color.darkened(0.28))
var draw_color: Color = color if is_visible else Color(0.045, 0.065, 0.065)
draw_colored_polygon(side_points, draw_color.darkened(0.28))
if is_selected:
if not is_visible:
draw_colored_polygon(points, Color(0.055, 0.075, 0.075))
elif is_selected:
draw_colored_polygon(points, color.lightened(0.22))
elif coord == home_tile:
draw_colored_polygon(points, Color(0.72, 0.58, 0.2))
elif is_owned:
draw_colored_polygon(points, Color(0.34, 0.52, 0.36))
elif is_hovered:
draw_colored_polygon(points, color.lightened(0.13))
else:
@@ -119,8 +147,14 @@ func _draw_tile(tile: Dictionary) -> void:
draw_polyline(_closed_points(points), Color(0.04, 0.065, 0.06, 0.72), 2.0)
if is_selected:
if not is_visible:
draw_polyline(_closed_points(points), Color(0.11, 0.15, 0.15, 0.75), 1.0)
elif is_selected:
draw_polyline(_closed_points(points), Color(0.95, 0.76, 0.28), 4.0)
elif coord == home_tile:
draw_polyline(_closed_points(points), Color(1.0, 0.88, 0.38), 3.0)
elif is_owned:
draw_polyline(_closed_points(points), Color(0.66, 0.9, 0.56), 2.5)
func _update_hover(mouse_position: Vector2) -> void:
@@ -143,15 +177,20 @@ func _update_hover(mouse_position: Vector2) -> void:
hovered_tile = closest
if hovered_tile.x != 9999:
var data: Dictionary = _tile_data(hovered_tile.x, hovered_tile.y)
tile_hovered.emit(hovered_tile.x, hovered_tile.y, str(data.get("terrain", "Open")))
var key: String = _tile_key(hovered_tile.x, hovered_tile.y)
var terrain: String = str(data.get("terrain", "Open")) if visible_tiles.has(key) else "Unexplored"
tile_hovered.emit(hovered_tile.x, hovered_tile.y, terrain)
queue_redraw()
func _tile_center(q: int, r: int) -> Vector2:
return _screen_point(_iso_world_point(q, r))
func _iso_world_point(q: int, r: int) -> Vector2:
var world_x: float = HEX_SIZE * SQRT_3 * (q + r * 0.5)
var world_y: float = HEX_SIZE * 1.5 * r
var iso: Vector2 = Vector2(world_x - world_y, (world_x + world_y) * ISO_Y_SCALE)
return _screen_point(iso)
return Vector2(world_x - world_y, (world_x + world_y) * ISO_Y_SCALE)
func _screen_point(world_point: Vector2) -> Vector2:
@@ -182,6 +221,42 @@ func _tile_data(q: int, r: int) -> Dictionary:
return {}
func set_home_location(q: int, r: int) -> void:
home_tile = Vector2i(q, r)
selected_tile = home_tile
_build_tiles_around(q, r, 9)
camera_offset = -_iso_world_point(q, r)
queue_redraw()
func set_visible_locations(locations: Array, username: String) -> void:
visible_tiles.clear()
owned_tiles.clear()
for item in locations:
if typeof(item) != TYPE_DICTIONARY:
continue
var location: Dictionary = item
var q: int = int(location.get("q", 0))
var r: int = int(location.get("r", 0))
var terrain: String = str(location.get("terrain", "Field"))
var owner: String = str(location.get("ownerUsername", ""))
var key: String = _tile_key(q, r)
visible_tiles[key] = location
_add_or_update_tile(q, r, terrain)
if not owner.is_empty() and owner == username:
owned_tiles[key] = location
queue_redraw()
func _tile_key(q: int, r: int) -> String:
return "%d,%d" % [q, r]
func _tile_height(q: int, r: int) -> float:
var distance: int = max(max(abs(q), abs(r)), abs(-q - r))
if distance <= 1:
@@ -207,6 +282,10 @@ func _terrain_name(q: int, r: int, height: float) -> String:
func _terrain_color(q: int, r: int, height: float) -> Color:
var terrain: String = _terrain_name(q, r, height)
return _terrain_color_for_name(terrain, q, r, height)
func _terrain_color_for_name(terrain: String, _q: int, _r: int, _height: float) -> Color:
match terrain:
"Command":
return Color(0.68, 0.58, 0.28)