Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[contracts] no resource lock during seige #1594

Merged
merged 16 commits into from
Sep 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions client/src/dojo/contractComponents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -983,12 +983,12 @@ export function defineContractComponents(world: World) {
ResourceTransferLock: (() => {
return defineComponent(
world,
{ entity_id: RecsType.Number, release_at: RecsType.BigInt },
{ entity_id: RecsType.Number, start_at: RecsType.BigInt, release_at: RecsType.BigInt },
{
metadata: {
namespace: "eternum",
name: "ResourceTransferLock",
types: ["u32", "u64"],
types: ["u32", "u64", "u64"],
customTypes: [],
},
},
Expand Down
47 changes: 36 additions & 11 deletions contracts/src/models/combat.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -466,7 +466,7 @@ impl ProtecteeCustomImpl of ProtecteeCustomTrait {
self.protectee_id != 0
}

fn protected_resources_holder(self: Protectee) -> ID {
fn protected_entity(self: Protectee) -> ID {
if self.is_other() {
self.protectee_id
} else {
Expand Down Expand Up @@ -522,9 +522,30 @@ impl BattleSideIntoFelt252 of Into<BattleSide, felt252> {

#[generate_trait]
impl BattleEscrowImpl of BattleEscrowTrait {
fn deposit_lock_immediately(ref self: Battle, world: IWorldDispatcher, army_protectee: Protectee) {
let army_protectee_id = army_protectee.protected_entity();
let mut army_resource_lock: ResourceTransferLock = get!(world, army_protectee_id, ResourceTransferLock);
army_resource_lock.assert_not_locked();

let now = starknet::get_block_timestamp();
assert!(army_resource_lock.start_at > now, "wrong lock invariant (1)");
assert!(army_resource_lock.release_at > now, "wrong lock invariant (2)");

army_resource_lock.start_at = now;
set!(world, (army_resource_lock));
}


fn deposit_balance(ref self: Battle, world: IWorldDispatcher, from_army: Army, from_army_protectee: Protectee) {
let from_army_protectee_id = from_army_protectee.protected_resources_holder();
let from_army_protectee_id = from_army_protectee.protected_entity();
let from_army_protectee_is_self: bool = !get!(world, from_army_protectee_id, Structure).is_structure();

// ensure resources were not previously locked
let mut from_army_resource_lock: ResourceTransferLock = get!(
world, from_army_protectee_id, ResourceTransferLock
);
from_army_resource_lock.assert_not_locked();

if from_army_protectee_is_self {
// detail items locked in box
let escrow_id = match from_army.battle_side {
Expand Down Expand Up @@ -552,15 +573,18 @@ impl BattleEscrowImpl of BattleEscrowTrait {
Option::None => { break; }
}
};
}

// lock the resources protected by the army
let mut from_army_resource_lock: ResourceTransferLock = get!(
world, from_army_protectee_id, ResourceTransferLock
);
from_army_resource_lock.assert_not_locked();
from_army_resource_lock.release_at = Bounded::MAX;
set!(world, (from_army_resource_lock));
// lock the resources protected by the army immediately
from_army_resource_lock.start_at = starknet::get_block_timestamp();
from_army_resource_lock.release_at = Bounded::MAX;
set!(world, (from_army_resource_lock));
} else {
// lock resources of the entity being protected starting from
// when the battle starts to account for battle.start_at delay
from_army_resource_lock.start_at = self.start_at;
from_army_resource_lock.release_at = Bounded::MAX;
set!(world, (from_army_resource_lock));
}
}

fn withdraw_balance_and_reward(
Expand All @@ -572,7 +596,7 @@ impl BattleEscrowImpl of BattleEscrowTrait {
BattleSide::Defence => { (self.defenders_resources_escrow_id, self.attackers_resources_escrow_id) }
};

let to_army_protectee_id = to_army_protectee.protected_resources_holder();
let to_army_protectee_id = to_army_protectee.protected_entity();
let to_army_protectee_is_self: bool = !get!(world, to_army_protectee_id, Structure).is_structure();

let winner_side: BattleSide = self.winner();
Expand Down Expand Up @@ -660,6 +684,7 @@ impl BattleEscrowImpl of BattleEscrowTrait {
// release lock on resource
let mut to_army_resource_lock: ResourceTransferLock = get!(world, to_army_protectee_id, ResourceTransferLock);
to_army_resource_lock.assert_locked();
to_army_resource_lock.start_at = starknet::get_block_timestamp();
to_army_resource_lock.release_at = starknet::get_block_timestamp();
set!(world, (to_army_resource_lock));
}
Expand Down
6 changes: 6 additions & 0 deletions contracts/src/models/resources.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ pub struct OwnedResourcesTracker {
pub struct ResourceTransferLock {
#[key]
entity_id: ID,
start_at: u64,
release_at: u64,
}

Expand All @@ -106,6 +107,11 @@ impl ResourceTransferLockCustomImpl of ResourceTransferLockCustomTrait {

fn is_open(self: ResourceTransferLock) -> bool {
let now = starknet::get_block_timestamp();
if self.start_at.is_non_zero() {
if now < self.start_at {
return true;
}
}
now >= self.release_at
}
}
Expand Down
15 changes: 13 additions & 2 deletions contracts/src/systems/combat/contracts.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -678,8 +678,9 @@ mod combat_systems {
battle.defence_army_health = defending_army_health.into();
battle.last_updated = now;
battle.start_at = now;
// add battle start time delay when a structure is being attacked.
// if the structure is the attacker, the battle starts immediately
if defending_army_protectee.is_other() {
// add delay when a structure is being attacked
battle.start_at = now + battle_config.battle_delay_seconds;
}

Expand Down Expand Up @@ -735,12 +736,17 @@ mod combat_systems {
assert!(defending_army.battle_id == battle_id, "army is not in battle");
assert!(defending_army.battle_side == BattleSide::Defence, "army is not on defensive");

let mut defending_army_protectee: Protectee = get!(world, defending_army_id, Protectee);
// this condition should not be possible unless there is a bug in `battle_start`
assert!(defending_army_protectee.is_other(), "only structures can force start");

let now = starknet::get_block_timestamp();
let mut battle = BattleCustomImpl::get(world, battle_id);
assert!(now < battle.start_at, "Battle already started");

// update battle
battle.start_at = now;
battle.deposit_lock_immediately(world, defending_army_protectee);
set!(world, (battle));
}

Expand Down Expand Up @@ -1344,7 +1350,12 @@ mod combat_systems {
set!(world, (structure_protector, Protectee { army_id, protectee_id: army_owner_id }));

// stop the army from sending or receiving resources
set!(world, (ResourceTransferLock { entity_id: army_id, release_at: Bounded::MAX }));
set!(
world,
(ResourceTransferLock {
entity_id: army_id, start_at: starknet::get_block_timestamp(), release_at: Bounded::MAX
})
);
army_id
}

Expand Down
Loading