updates
This commit is contained in:
@@ -46,7 +46,10 @@ var building_box: VBoxContainer
|
||||
var building_label: Label
|
||||
var building_bar: ProgressBar
|
||||
var progress_panel: PanelContainer
|
||||
var progress_stack: VBoxContainer
|
||||
var action_buttons: HBoxContainer
|
||||
var training_items: Array[Dictionary] = []
|
||||
var training_item_boxes: Array[VBoxContainer] = []
|
||||
var training_started_unix := 0.0
|
||||
var training_completes_unix := 0.0
|
||||
var training_completion_refresh_requested := false
|
||||
@@ -433,12 +436,13 @@ func _build_map_overlays(map_layer: Control) -> void:
|
||||
progress_margin.add_theme_constant_override("margin_bottom", 10)
|
||||
progress_panel.add_child(progress_margin)
|
||||
|
||||
var progress_stack := VBoxContainer.new()
|
||||
progress_stack = VBoxContainer.new()
|
||||
progress_stack.add_theme_constant_override("separation", 8)
|
||||
progress_margin.add_child(progress_stack)
|
||||
|
||||
training_box = _progress_overlay_item("Training")
|
||||
progress_stack.add_child(training_box)
|
||||
training_item_boxes.append(training_box)
|
||||
training_label = training_box.get_child(0) as Label
|
||||
training_bar = training_box.get_child(1) as ProgressBar
|
||||
|
||||
@@ -683,7 +687,7 @@ func _confirm_scout_claim() -> void:
|
||||
selected_q = pending_move_q
|
||||
selected_r = pending_move_r
|
||||
selected_can_claim = true
|
||||
_claim_selected_tile()
|
||||
_move_selected_scouts(pending_move_q, pending_move_r, true)
|
||||
|
||||
|
||||
func _confirm_worker_assign() -> void:
|
||||
@@ -790,7 +794,7 @@ func _can_build_on_selected_tile(required_terrain: String) -> bool:
|
||||
|
||||
|
||||
func _can_claim_selected_tile() -> bool:
|
||||
return selected_can_claim and completed_scout_count > 0 and grid_view and grid_view.has_owned_neighbor(selected_q, selected_r)
|
||||
return selected_can_claim and selected_scout_count > 0 and completed_scout_count > 0 and grid_view and grid_view.has_owned_neighbor(selected_q, selected_r)
|
||||
|
||||
|
||||
func _can_claim_tile(q: int, r: int) -> bool:
|
||||
@@ -1253,11 +1257,13 @@ func _on_units_request_completed(result: int, response_code: int, _headers: Pack
|
||||
_clear_removed_selected_unit()
|
||||
unit_label.text = "Scouts: %d | Peasants: %d | Archers: %d | Queue: %d" % [completed_scout_count, completed_peasant_count, completed_archer_count, training.size()]
|
||||
_update_action_buttons()
|
||||
_load_visible_locations()
|
||||
if units_reload_queued:
|
||||
units_reload_queued = false
|
||||
call_deferred("_load_units")
|
||||
|
||||
if training.is_empty():
|
||||
training_items.clear()
|
||||
training_started_unix = 0.0
|
||||
training_completes_unix = 0.0
|
||||
active_training_label = "Training"
|
||||
@@ -1265,13 +1271,25 @@ func _on_units_request_completed(result: int, response_code: int, _headers: Pack
|
||||
_update_training_bar()
|
||||
return
|
||||
|
||||
if typeof(training[0]) != TYPE_DICTIONARY:
|
||||
return
|
||||
training_items.clear()
|
||||
for item in training:
|
||||
if typeof(item) != TYPE_DICTIONARY:
|
||||
continue
|
||||
var training_item: Dictionary = item
|
||||
training_items.append({
|
||||
"label": _unit_display_name(str(training_item.get("unitType", "Training"))),
|
||||
"started": _parse_utc_timestamp(str(training_item.get("startedAtUtc", ""))),
|
||||
"completes": _parse_utc_timestamp(str(training_item.get("completesAtUtc", "")))
|
||||
})
|
||||
|
||||
var active_training: Dictionary = training[0]
|
||||
active_training_label = _unit_display_name(str(active_training.get("unitType", "Training")))
|
||||
training_started_unix = _parse_utc_timestamp(str(active_training.get("startedAtUtc", "")))
|
||||
training_completes_unix = _parse_utc_timestamp(str(active_training.get("completesAtUtc", "")))
|
||||
if training_items.is_empty():
|
||||
training_started_unix = 0.0
|
||||
training_completes_unix = 0.0
|
||||
else:
|
||||
var active_training: Dictionary = training_items[0]
|
||||
active_training_label = str(active_training.get("label", "Training"))
|
||||
training_started_unix = float(active_training.get("started", 0.0))
|
||||
training_completes_unix = float(active_training.get("completes", 0.0))
|
||||
training_completion_refresh_requested = false
|
||||
_update_training_bar()
|
||||
|
||||
@@ -1403,7 +1421,7 @@ func _move_selected_archers(to_q: int, to_r: int) -> void:
|
||||
coordinate_label.text = "Could not contact the unit move service."
|
||||
|
||||
|
||||
func _move_selected_scouts(to_q: int, to_r: int) -> void:
|
||||
func _move_selected_scouts(to_q: int, to_r: int, claim_on_arrival: bool = false) -> void:
|
||||
if selected_scout_count <= 0:
|
||||
return
|
||||
if to_q == selected_scout_q and to_r == selected_scout_r:
|
||||
@@ -1421,7 +1439,7 @@ func _move_selected_scouts(to_q: int, to_r: int) -> void:
|
||||
if move_units_request.get_http_client_status() != HTTPClient.STATUS_DISCONNECTED:
|
||||
return
|
||||
|
||||
coordinate_label.text = "Ordering %d Scouts to move to q:%d r:%d..." % [selected_scout_count, to_q, to_r]
|
||||
coordinate_label.text = "Ordering Scout to claim q:%d r:%d..." % [to_q, to_r] if claim_on_arrival else "Ordering %d Scouts to move to q:%d r:%d..." % [selected_scout_count, to_q, to_r]
|
||||
var error: int = move_units_request.request(
|
||||
LOCATIONS_BASE_URL + "/api/units/move",
|
||||
PackedStringArray([
|
||||
@@ -1434,7 +1452,8 @@ func _move_selected_scouts(to_q: int, to_r: int) -> void:
|
||||
"fromQ": selected_scout_q,
|
||||
"fromR": selected_scout_r,
|
||||
"toQ": to_q,
|
||||
"toR": to_r
|
||||
"toR": to_r,
|
||||
"claimOnArrival": claim_on_arrival
|
||||
})
|
||||
)
|
||||
if error != OK:
|
||||
@@ -1582,6 +1601,9 @@ func _claim_selected_tile() -> void:
|
||||
if not selected_can_claim:
|
||||
coordinate_label.text = "Select a visible unclaimed tile to send a scout."
|
||||
return
|
||||
if selected_scout_count <= 0:
|
||||
coordinate_label.text = "Select a Scout, then choose Claim on the target tile."
|
||||
return
|
||||
if completed_scout_count <= 0:
|
||||
coordinate_label.text = "Train a scout before claiming territory."
|
||||
return
|
||||
@@ -1594,23 +1616,8 @@ func _claim_selected_tile() -> void:
|
||||
coordinate_label.text = "No auth token available. Territory was not claimed."
|
||||
return
|
||||
|
||||
if claim_request.get_http_client_status() != HTTPClient.STATUS_DISCONNECTED:
|
||||
return
|
||||
|
||||
claim_button.disabled = true
|
||||
coordinate_label.text = "Sending scout to claim q:%d r:%d..." % [selected_q, selected_r]
|
||||
var error: int = claim_request.request(
|
||||
LOCATIONS_BASE_URL + "/api/locations/claim",
|
||||
PackedStringArray([
|
||||
"Content-Type: application/json",
|
||||
"Authorization: Bearer %s" % access_token
|
||||
]),
|
||||
HTTPClient.METHOD_POST,
|
||||
JSON.stringify({ "q": selected_q, "r": selected_r })
|
||||
)
|
||||
if error != OK:
|
||||
_update_action_buttons()
|
||||
coordinate_label.text = "Could not contact the locations service."
|
||||
_move_selected_scouts(selected_q, selected_r, true)
|
||||
|
||||
|
||||
func _on_claim_request_completed(result: int, response_code: int, _headers: PackedStringArray, body: PackedByteArray) -> void:
|
||||
@@ -1816,30 +1823,55 @@ func _update_tick_bar() -> void:
|
||||
|
||||
|
||||
func _update_training_bar() -> void:
|
||||
if not training_bar or not training_label:
|
||||
if not training_bar or not training_label or not progress_stack:
|
||||
return
|
||||
|
||||
if training_started_unix <= 0.0 or training_completes_unix <= 0.0:
|
||||
training_box.visible = false
|
||||
if training_items.is_empty():
|
||||
for box in training_item_boxes:
|
||||
box.visible = false
|
||||
training_bar.value = 0.0
|
||||
training_label.text = "Training: idle"
|
||||
_update_progress_panel_visibility()
|
||||
return
|
||||
|
||||
training_box.visible = true
|
||||
var now: float = Time.get_unix_time_from_system()
|
||||
var duration: float = max(1.0, training_completes_unix - training_started_unix)
|
||||
var elapsed: float = clamp(now - training_started_unix, 0.0, duration)
|
||||
var remaining: int = int(max(0, int(ceil(training_completes_unix - now))))
|
||||
training_bar.value = elapsed / duration
|
||||
while training_item_boxes.size() < training_items.size():
|
||||
var box := _progress_overlay_item("Training")
|
||||
progress_stack.add_child(box)
|
||||
progress_stack.move_child(building_box, progress_stack.get_child_count() - 1)
|
||||
training_item_boxes.append(box)
|
||||
|
||||
if remaining <= 0:
|
||||
training_label.text = "%s: ready" % active_training_label
|
||||
if not training_completion_refresh_requested:
|
||||
training_completion_refresh_requested = true
|
||||
_load_units()
|
||||
else:
|
||||
training_label.text = "%s: %ds" % [active_training_label, remaining]
|
||||
var any_ready := false
|
||||
for index in range(training_item_boxes.size()):
|
||||
var box: VBoxContainer = training_item_boxes[index]
|
||||
if index >= training_items.size():
|
||||
box.visible = false
|
||||
continue
|
||||
|
||||
var item: Dictionary = training_items[index]
|
||||
var label := box.get_child(0) as Label
|
||||
var bar := box.get_child(1) as ProgressBar
|
||||
var started := float(item.get("started", 0.0))
|
||||
var completes := float(item.get("completes", 0.0))
|
||||
var item_label := str(item.get("label", "Training"))
|
||||
if started <= 0.0 or completes <= 0.0:
|
||||
box.visible = false
|
||||
continue
|
||||
|
||||
box.visible = true
|
||||
var duration: float = max(1.0, completes - started)
|
||||
var elapsed: float = clamp(now - started, 0.0, duration)
|
||||
var remaining: int = int(max(0, int(ceil(completes - now))))
|
||||
bar.value = elapsed / duration
|
||||
if remaining <= 0:
|
||||
label.text = "%s: ready" % item_label
|
||||
any_ready = true
|
||||
else:
|
||||
label.text = "%s: %ds" % [item_label, remaining]
|
||||
|
||||
if any_ready and not training_completion_refresh_requested:
|
||||
training_completion_refresh_requested = true
|
||||
_load_units()
|
||||
_update_progress_panel_visibility()
|
||||
|
||||
|
||||
@@ -1875,7 +1907,12 @@ func _update_building_timer() -> void:
|
||||
|
||||
func _update_progress_panel_visibility() -> void:
|
||||
if progress_panel:
|
||||
progress_panel.visible = (training_box and training_box.visible) or (building_box and building_box.visible)
|
||||
var has_training := false
|
||||
for box in training_item_boxes:
|
||||
if box.visible:
|
||||
has_training = true
|
||||
break
|
||||
progress_panel.visible = has_training or (building_box and building_box.visible)
|
||||
|
||||
|
||||
func _sync_active_building_timer(locations: Array, username: String) -> void:
|
||||
|
||||
@@ -181,6 +181,7 @@ func _draw_tile(tile: Dictionary) -> void:
|
||||
var visible_location: Dictionary = visible_tiles.get(key, {})
|
||||
var building_type: String = _nullable_string(visible_location.get("buildingType", ""))
|
||||
var building_status: String = _nullable_string(visible_location.get("buildingStatus", ""))
|
||||
var worker_unit_id: String = _nullable_string(visible_location.get("workerUnitId", ""))
|
||||
if coord == home_tile:
|
||||
_draw_town_hall_marker(center, height)
|
||||
elif building_type == "LogCamp" and (building_status == "Built" or building_status.is_empty()):
|
||||
@@ -193,6 +194,8 @@ func _draw_tile(tile: Dictionary) -> void:
|
||||
_draw_barracks_marker(center, height)
|
||||
elif not building_type.is_empty():
|
||||
_draw_building_marker(center, height)
|
||||
if _building_needs_worker(building_type, building_status, worker_unit_id):
|
||||
_draw_missing_worker_marker(center, height)
|
||||
|
||||
var archer_count := _archer_count_at(q, r)
|
||||
if archer_count > 0:
|
||||
@@ -585,6 +588,30 @@ func _draw_building_marker(center: Vector2, height: float) -> void:
|
||||
draw_line(left, right.lerp(top_right, 0.2), post_color.darkened(0.12), 1.5 * zoom)
|
||||
|
||||
|
||||
func _building_needs_worker(building_type: String, building_status: String, worker_unit_id: String) -> bool:
|
||||
if not worker_unit_id.is_empty():
|
||||
return false
|
||||
if building_type != "LogCamp" and building_type != "Mine" and building_type != "Farm":
|
||||
return false
|
||||
return building_status == "Built" or building_status.is_empty()
|
||||
|
||||
|
||||
func _draw_missing_worker_marker(center: Vector2, height: float) -> void:
|
||||
var marker_center: Vector2 = center + Vector2(20.0 * zoom, -height * zoom - 27.0 * zoom)
|
||||
var marker_scale: float = zoom
|
||||
var badge_radius: float = 7.0 * marker_scale
|
||||
var fill_color := Color(0.93, 0.66, 0.18, 0.96)
|
||||
var edge_color := Color(0.18, 0.10, 0.02, 0.92)
|
||||
var icon_color := Color(0.10, 0.07, 0.03, 0.96)
|
||||
|
||||
draw_circle(marker_center + Vector2(1, 1) * marker_scale, badge_radius + 1.0 * marker_scale, Color(0.0, 0.0, 0.0, 0.35))
|
||||
draw_circle(marker_center, badge_radius, fill_color)
|
||||
draw_arc(marker_center, badge_radius, 0.0, TAU, 24, edge_color, 1.4 * marker_scale)
|
||||
draw_circle(marker_center + Vector2(0, -2.3) * marker_scale, 2.0 * marker_scale, icon_color)
|
||||
draw_rect(Rect2(marker_center + Vector2(-2.2, 0.8) * marker_scale, Vector2(4.4, 4.8) * marker_scale), icon_color, true)
|
||||
draw_line(marker_center + Vector2(-5.0, 5.8) * marker_scale, marker_center + Vector2(5.0, -5.8) * marker_scale, edge_color, 1.7 * marker_scale)
|
||||
|
||||
|
||||
func _draw_archer_unit_marker(center: Vector2, height: float, count: int) -> void:
|
||||
var marker_center: Vector2 = _archer_marker_center(center, height)
|
||||
var marker_scale: float = zoom
|
||||
|
||||
@@ -87,6 +87,10 @@ public class LocationsController : ControllerBase
|
||||
{
|
||||
return NotFound();
|
||||
}
|
||||
if (!User.IsInRole("SUPER"))
|
||||
{
|
||||
return BadRequest("Use a Scout move order to claim territory on arrival.");
|
||||
}
|
||||
|
||||
if (!User.IsInRole("SUPER") && !await _locations.IsAdjacentToOwnedAsync(username, request.Q, request.R))
|
||||
{
|
||||
|
||||
@@ -15,6 +15,7 @@ public class MoveUnitSquadRequest
|
||||
public int FromR { get; set; }
|
||||
public int ToQ { get; set; }
|
||||
public int ToR { get; set; }
|
||||
public bool ClaimOnArrival { get; set; }
|
||||
}
|
||||
|
||||
public class DismissUnitSquadRequest
|
||||
@@ -75,6 +76,7 @@ public class UnitInstanceResponse
|
||||
public DateTime LastMovementRefillAtUtc { get; set; }
|
||||
public int? DestinationQ { get; set; }
|
||||
public int? DestinationR { get; set; }
|
||||
public bool ClaimOnArrival { get; set; }
|
||||
public DateTime? MovementStartedAtUtc { get; set; }
|
||||
public DateTime? MovementCompletesAtUtc { get; set; }
|
||||
public DateTime CreatedAtUtc { get; set; }
|
||||
@@ -93,6 +95,7 @@ public class UnitInstanceResponse
|
||||
LastMovementRefillAtUtc = unit.LastMovementRefillAtUtc,
|
||||
DestinationQ = unit.DestinationQ,
|
||||
DestinationR = unit.DestinationR,
|
||||
ClaimOnArrival = unit.ClaimOnArrival,
|
||||
MovementStartedAtUtc = unit.MovementStartedAtUtc,
|
||||
MovementCompletesAtUtc = unit.MovementCompletesAtUtc,
|
||||
CreatedAtUtc = unit.CreatedAtUtc,
|
||||
|
||||
@@ -19,6 +19,7 @@ public class UnitInstance
|
||||
public DateTime LastMovementRefillAtUtc { get; set; } = DateTime.UtcNow;
|
||||
public int? DestinationQ { get; set; }
|
||||
public int? DestinationR { get; set; }
|
||||
public bool ClaimOnArrival { get; set; }
|
||||
public DateTime? MovementStartedAtUtc { get; set; }
|
||||
public DateTime? MovementCompletesAtUtc { get; set; }
|
||||
public string? SourceTrainingId { get; set; }
|
||||
|
||||
@@ -190,6 +190,10 @@ public class UnitTrainingService
|
||||
{
|
||||
throw new ArgumentException("Only Scouts, Archers, and Peasants can be moved right now.", nameof(request.UnitType));
|
||||
}
|
||||
if (request.ClaimOnArrival && normalizedUnitType != ScoutUnitType)
|
||||
{
|
||||
throw new ArgumentException("Only Scouts can claim territory.", nameof(request.ClaimOnArrival));
|
||||
}
|
||||
|
||||
if (request.FromQ == request.ToQ && request.FromR == request.ToR)
|
||||
{
|
||||
@@ -206,6 +210,10 @@ public class UnitTrainingService
|
||||
{
|
||||
throw new InvalidOperationException("Peasants can only move within your controlled territory.");
|
||||
}
|
||||
if (request.ClaimOnArrival && !await IsAdjacentToOwnedAsync(username, request.ToQ, request.ToR))
|
||||
{
|
||||
throw new InvalidOperationException("Scout claims must target territory adjacent to controlled territory.");
|
||||
}
|
||||
|
||||
var now = DateTime.UtcNow;
|
||||
var unitFilter = Builders<UnitInstance>.Filter.And(
|
||||
@@ -234,26 +242,24 @@ public class UnitTrainingService
|
||||
throw new InvalidOperationException("That squad has no movement remaining this tick.");
|
||||
}
|
||||
|
||||
var movingUnitIds = request.ClaimOnArrival
|
||||
? units.OrderBy(x => x.Id).Take(1).Select(x => x.Id).ToList()
|
||||
: units.Select(x => x.Id).ToList();
|
||||
var movementCompletesAt = now.AddMinutes(1);
|
||||
await _units.UpdateManyAsync(
|
||||
unitFilter,
|
||||
Builders<UnitInstance>.Filter.In(x => x.Id, movingUnitIds),
|
||||
Builders<UnitInstance>.Update
|
||||
.Set(x => x.Status, "Moving")
|
||||
.Inc(x => x.MovementRemaining, -1)
|
||||
.Set(x => x.DestinationQ, request.ToQ)
|
||||
.Set(x => x.DestinationR, request.ToR)
|
||||
.Set(x => x.ClaimOnArrival, request.ClaimOnArrival)
|
||||
.Set(x => x.MovementStartedAtUtc, now)
|
||||
.Set(x => x.MovementCompletesAtUtc, movementCompletesAt)
|
||||
.Set(x => x.UpdatedAtUtc, now));
|
||||
|
||||
return await _units.Find(x =>
|
||||
x.Username == username &&
|
||||
x.UnitType == normalizedUnitType &&
|
||||
x.Status == "Moving" &&
|
||||
x.Q == request.FromQ &&
|
||||
x.R == request.FromR &&
|
||||
x.DestinationQ == request.ToQ &&
|
||||
x.DestinationR == request.ToR)
|
||||
movingUnitIds.Contains(x.Id))
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
@@ -310,6 +316,7 @@ public class UnitTrainingService
|
||||
.Set(x => x.Status, "Idle")
|
||||
.Set(x => x.MovementPerTick, movementPerTick)
|
||||
.Set(x => x.MovementRemaining, movementPerTick)
|
||||
.Set(x => x.ClaimOnArrival, false)
|
||||
.Unset(x => x.MovementStartedAtUtc)
|
||||
.Unset(x => x.MovementCompletesAtUtc)
|
||||
.Set(x => x.UpdatedAtUtc, now));
|
||||
@@ -331,6 +338,7 @@ public class UnitTrainingService
|
||||
.Set(x => x.MovementRemaining, movementPerTick)
|
||||
.Unset(x => x.DestinationQ)
|
||||
.Unset(x => x.DestinationR)
|
||||
.Set(x => x.ClaimOnArrival, false)
|
||||
.Unset(x => x.MovementStartedAtUtc)
|
||||
.Unset(x => x.MovementCompletesAtUtc)
|
||||
.Set(x => x.UpdatedAtUtc, now));
|
||||
@@ -371,10 +379,16 @@ public class UnitTrainingService
|
||||
.Set(x => x.LastMovementRefillAtUtc, now)
|
||||
.Unset(x => x.DestinationQ)
|
||||
.Unset(x => x.DestinationR)
|
||||
.Set(x => x.ClaimOnArrival, false)
|
||||
.Unset(x => x.MovementStartedAtUtc)
|
||||
.Unset(x => x.MovementCompletesAtUtc)
|
||||
.Set(x => x.UpdatedAtUtc, now));
|
||||
|
||||
if (unit.UnitType == ScoutUnitType && unit.ClaimOnArrival)
|
||||
{
|
||||
await TryClaimWithArrivedScoutAsync(unit, destinationQ, destinationR, now);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -409,6 +423,84 @@ public class UnitTrainingService
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<bool> IsAdjacentToOwnedAsync(string username, int q, int r)
|
||||
{
|
||||
var owned = await _locations.Find(x => x.OwnerUsername == username).ToListAsync();
|
||||
return owned.Any(location => HexDistance(location.Q, location.R, q, r) == 1);
|
||||
}
|
||||
|
||||
private async Task TryClaimWithArrivedScoutAsync(UnitInstance scout, int q, int r, DateTime now)
|
||||
{
|
||||
var target = await _locations.Find(x => x.Q == q && x.R == r).FirstOrDefaultAsync();
|
||||
if (target is not null)
|
||||
{
|
||||
if (string.Equals(target.OwnerUsername, scout.Username, StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(target.Kind, "Home", StringComparison.OrdinalIgnoreCase) ||
|
||||
!string.IsNullOrWhiteSpace(target.BuildingType))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var hasBlockingUnit = await _units.Find(x =>
|
||||
x.Id != scout.Id &&
|
||||
x.Q == q &&
|
||||
x.R == r)
|
||||
.AnyAsync();
|
||||
if (hasBlockingUnit)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!await IsAdjacentToOwnedAsync(scout.Username, q, r))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var claimed = false;
|
||||
if (target is null)
|
||||
{
|
||||
var location = new Location
|
||||
{
|
||||
Q = q,
|
||||
R = r,
|
||||
Terrain = "Field",
|
||||
Kind = "Claimed",
|
||||
OwnerUsername = scout.Username,
|
||||
Level = 1,
|
||||
CreatedAtUtc = now,
|
||||
UpdatedAtUtc = now
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
await _locations.InsertOneAsync(location);
|
||||
claimed = true;
|
||||
}
|
||||
catch (MongoWriteException)
|
||||
{
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = await _locations.UpdateOneAsync(
|
||||
x => x.Id == target.Id &&
|
||||
x.Kind != "Home" &&
|
||||
(x.BuildingType == null || x.BuildingType == "") &&
|
||||
x.OwnerUsername != scout.Username,
|
||||
Builders<Location>.Update
|
||||
.Set(x => x.OwnerUsername, scout.Username)
|
||||
.Set(x => x.Kind, "Claimed")
|
||||
.Set(x => x.UpdatedAtUtc, now));
|
||||
claimed = result.ModifiedCount > 0;
|
||||
}
|
||||
|
||||
if (claimed)
|
||||
{
|
||||
await _units.DeleteOneAsync(x => x.Id == scout.Id);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task CompleteFinishedBuildingsAsync(string username)
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
|
||||
Reference in New Issue
Block a user