From c2051d5277d228fa005211fc3206ebdf108924ff Mon Sep 17 00:00:00 2001 From: Credence Date: Wed, 8 Jan 2025 04:40:32 +0100 Subject: [PATCH] new production wip --- contracts/game/src/constants.cairo | 3 +- contracts/game/src/models/buildings.cairo | 7 +- .../game/src/models/production/labor.cairo | 13 ++- .../src/models/production/production.cairo | 2 +- contracts/game/src/models/resources.cairo | 95 +++++++++++++------ 5 files changed, 83 insertions(+), 37 deletions(-) diff --git a/contracts/game/src/constants.cairo b/contracts/game/src/constants.cairo index ff349911a..7d01687ca 100644 --- a/contracts/game/src/constants.cairo +++ b/contracts/game/src/constants.cairo @@ -113,6 +113,7 @@ mod ResourceTypes { // e.g Stone labor = 255 - 1 = 254 } +const LAST_REGULAR_RESOURCE_ID: u8 = 31; fn resource_type_name(resource_type: u8) -> ByteArray { if resource_type == 1 { "STONE" @@ -174,7 +175,7 @@ fn resource_type_name(resource_type: u8) -> ByteArray { "LORDS" } else if resource_type == 30 { "WHEAT" - } else if resource_type == 31 { + } else if resource_type == LAST_REGULAR_RESOURCE_ID { "FISH" // LABOR diff --git a/contracts/game/src/models/buildings.cairo b/contracts/game/src/models/buildings.cairo index 65fe35841..6efedd119 100644 --- a/contracts/game/src/models/buildings.cairo +++ b/contracts/game/src/models/buildings.cairo @@ -186,12 +186,9 @@ impl BuildingProductionImpl of BuildingProductionTrait { // get labor resource let mut labor_resource_type - = LaborImpl::labor_type_from_resource(produced_resource_type); - - // we expect labor resource to not be produceable so it's okay to - // read it from the world storage rather than the resourceimpl::get() + = LaborImpl::labor_resource_from_regular(produced_resource_type); let mut labor_resource: Resource - = world.read_model((self.outer_entity_id, labor_resource_type)); + = ResourceImpl::get(ref world, (self.outer_entity_id, labor_resource_type)); // update production labor finish tick let production_config: ProductionConfig = world.read_model(produced_resource_type); diff --git a/contracts/game/src/models/production/labor.cairo b/contracts/game/src/models/production/labor.cairo index bbd5f86c5..9de918f92 100644 --- a/contracts/game/src/models/production/labor.cairo +++ b/contracts/game/src/models/production/labor.cairo @@ -1,6 +1,7 @@ use dojo::model::ModelStorage; use dojo::world::WorldStorage; use s0_eternum::alias::ID; +use s0_eternum::constants::{LAST_REGULAR_RESOURCE_ID}; use s0_eternum::models::config::{LaborConfig}; use s0_eternum::models::config::{TickConfig, TickImpl, TickTrait}; use s0_eternum::models::resources::{Resource, ResourceImpl}; @@ -9,10 +10,18 @@ use s0_eternum::models::resources::{Resource, ResourceImpl}; #[generate_trait] impl LaborImpl LaborTrait { - fn labor_type_from_resource(resource_type: u8) -> u8 { + fn labor_resource_from_regular(resource_type: u8) -> u8 { return 255 - resource_type; } + fn resource_from_labor(labor_type: u8) -> u8 { + return 255 - labor_type; + } + + fn is_labor(resource_type: u8) -> bool { + return resource_type != 255 && resource_type >= 255 - LAST_LABOR_RESOURCE_ID; + } + fn make_labor(ref world: WorldStorage, entity_id: ID, resource_type: u8, labor_amount: u128) { assert!(resource_type.is_non_zero(), "can't make labor for 0 resource"); @@ -37,7 +46,7 @@ impl LaborImpl LaborTrait { } // make labor resource - let labor_resource_type = Self::labor_type_from_resource(resource_type); + let labor_resource_type = Self::labor_resource_from_regular(resource_type); let labor_resource = ResourceImpl::get(ref world, (entity_id, labor_resource_type)); labor_resource.add(labor_amount); labor_resource.save(ref world); diff --git a/contracts/game/src/models/production/production.cairo b/contracts/game/src/models/production/production.cairo index bd08683f0..39921a0cc 100644 --- a/contracts/game/src/models/production/production.cairo +++ b/contracts/game/src/models/production/production.cairo @@ -132,7 +132,7 @@ impl ProductionLaborImpl of ProductionLaborTrait { let labor_cost_per_tick = (*production_config).labor_amount; assert!(labor_cost_per_tick.is_non_zero(), "labor cost amount not set"); - let labor_tick_amount = labor.balance / labor_cost_per_tick; + let labor_tick_amount = labor.balance / (labor_cost_per_tick * connected_production.building_count.into()); connected_production.labor_finish_tick = (*tick).current() + labor_tick_amount; connected_production.last_updated_tick = (*tick).current(); } diff --git a/contracts/game/src/models/resources.cairo b/contracts/game/src/models/resources.cairo index 9d0ca7c27..662018576 100644 --- a/contracts/game/src/models/resources.cairo +++ b/contracts/game/src/models/resources.cairo @@ -13,7 +13,8 @@ use s0_eternum::models::config::{ }; use s0_eternum::models::config::{WeightConfigImpl, WeightConfig}; -use s0_eternum::models::production::{Production, ProductionOutputImpl, ProductionRateTrait}; +use s0_eternum::models::production::{Production, ProductionTrait, ProductionLaborImpl}; +use s0_eternum::models::production::labor::{LaborImpl, LaborTrait}; use s0_eternum::models::realm::Realm; use s0_eternum::models::structure::StructureTrait; use s0_eternum::models::structure::{Structure, StructureCategory}; @@ -171,17 +172,32 @@ impl ResourceFoodImpl of ResourceFoodTrait { impl ResourceImpl of ResourceTrait { fn get(ref world: WorldStorage, key: (ID, u8)) -> Resource { let mut resource: Resource = world.read_model(key); - assert!(resource.resource_type.is_non_zero(), "resource type not found"); assert!(resource.entity_id.is_non_zero(), "entity id not found"); - - resource.harvest(ref world); - - // if resource is labor, we need to update the production - - // how to know if resource is labor? - // 255 - resource_type > 200 - - // we check production of resource for + assert!( + resource.resource_type != 0, + && resource.resource_type != 255, + && resource.resource_type <= LAST_REGULAR_RESOURCE_ID, // regular resources + && resource.resource_type >= 255 - LAST_LABOR_RESOURCE_ID, // labor resources + "resource type not found" + ); + + let entity_structure: Structure = world.read_model(self.entity_id); + let entity_is_structure = entity_structure.is_structure(); + if entity_is_structure { + if LaborImpl::is_labor(resource.resource_type) { + let regular_resource_type = LaborImpl::resource_from_labor(resource.resource_type); + let mut regular_resource: Resource + = world.read_model((resource.entity_id, regular_resource_type)); + let labor_resource = resource; + regular_resource.update(ref labor_resource, ref world); + } else { + let labor_resource_type = LaborImpl::labor_resource_from_regular(self.resource_type); + let mut labor_resource: Resource = world.read_model((self.entity_id, labor_resource_type)); + let regular_resource = resource; + regular_resource.update(ref labor_resource, ref world); + } + } + return resource; } @@ -212,27 +228,42 @@ impl ResourceImpl of ResourceTrait { return; }; - // ensure realm has enough store houses to keep resource balance let entity_structure: Structure = world.read_model(self.entity_id); - let entity_is_structure = entity_structure.is_structure(); - if entity_is_structure { + if entity_structure.is_structure() { + // limit balance by storehouse capacity self.limit_balance_by_storehouse_capacity(ref world); + + // update the related production when labor resource is updated + if LaborImpl::is_labor(self.resource_type) { + let regular_resource_type = LaborImpl::resource_from_labor(resource.resource_type); + let mut regular_resource_production: Production + = world.read_model((self.entity_id, regular_resource_type)); + + if regular_resource_production.has_building() { + // check that the connected resource has already harvested production + let tick = TickImpl::get_default_tick_config(ref world); + assert!( + regular_resource_production.last_updated_tick == tick.current(), + "{} production has not been harvested", resource_type_name(regular_resource_type) + ); + + // update labor finish time + let production_config: ProductionConfig = world.read_model(regular_resource_type); + ProductionLaborImpl::update_connected_production( + ref labor_resource, + ref regular_resource_production, + @tick, @production_config + ); + world.write_model(@regular_resource_production); + } + } } // save the updated resource world.write_model(@self); - if entity_is_structure { - // sync end ticks of resources that use this resource in their production - // e.g `self` may be wheat resource and is stone, coal and gold are used - // in production of wheat, we update their exhaustion ticks - ProductionOutputImpl::sync_all_inputs_exhaustion_ticks_for(@self, ref world); - } - - // Update the entity's owned resources tracker - + // update the entity's resource tracker let mut entity_owned_resources: OwnedResourcesTracker = world.read_model(self.entity_id); - if self.balance == 0 { if entity_owned_resources.owns_resource_type(self.resource_type) { entity_owned_resources.set_resource_ownership(self.resource_type, false); @@ -273,20 +304,28 @@ impl ResourceImpl of ResourceTrait { let storehouse_capacity_grams_with_precision = storehouse_capacity_grams * RESOURCE_PRECISION; let max_weight_grams = min(resource_weight_grams_with_precision, storehouse_capacity_grams_with_precision); - let max_balance = max_weight_grams / resource_weight_config.weight_gram; self.balance = max_balance } - fn harvest(ref self: Resource, ref world: WorldStorage) { + fn update(ref self: Resource, ref labor_resource: Resource, ref world: WorldStorage) { let mut production: Production = world.read_model((self.entity_id, self.resource_type)); let tick = TickImpl::get_default_tick_config(ref world); - if production.is_active() && production.last_updated_tick != tick.current() { - production.harvest(ref self, @tick); + if production.has_building() && production.last_updated_tick != tick.current() { + + // harvest the production + let production_config: ProductionConfig = world.read_model(produced_resource_type); + production.harvest(ref self, ref labor_resource, @tick, @production_config); + + // limit balance by storehouse capacity self.limit_balance_by_storehouse_capacity(ref world); + labor_resource.limit_balance_by_storehouse_capacity(ref world); + + // save the updated resources world.write_model(@self); world.write_model(@production); + world.write_model(@labor_resource); } } }