diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index dcc51a6..c7ea52b 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -30,7 +30,7 @@ jobs: cd rust/main_logic cargo tarpaulin --out Xml --output-dir ../../ - name: Upload to Codecov - uses: codecov/codecov-action@v3 + uses: codecov/codecov-action@v4.0.1 with: token: ${{ secrets.CODECOV_TOKEN }} fail_ci_if_error: true diff --git a/godot/world_objects/objects/dirt_block.tres b/godot/world_objects/objects/dirt_block.tres deleted file mode 100644 index 3ffc25f..0000000 --- a/godot/world_objects/objects/dirt_block.tres +++ /dev/null @@ -1,30 +0,0 @@ -[gd_resource type="Resource" script_class="StaticObject" load_steps=7 format=3 uid="uid://dewgpakhsyo2h"] - -[ext_resource type="Script" path="res://world_objects/types/static/static.gd" id="1_846ss"] -[ext_resource type="Script" path="res://world_objects/types/static/state.gd" id="1_fblsk"] -[ext_resource type="Texture2D" uid="uid://ojnsm3dp50rt" path="res://assets/objects/static/dirt_block.png" id="2_6nqfm"] -[ext_resource type="Script" path="res://world_objects/tiles/object_tile.gd" id="4_5nua1"] - -[sub_resource type="Resource" id="Resource_v52p7"] -script = ExtResource("1_fblsk") -id = 0 - -[sub_resource type="Resource" id="Resource_pduds"] -script = ExtResource("4_5nua1") -texture = ExtResource("2_6nqfm") -y_offset = 0 - -[resource] -script = ExtResource("1_846ss") -tile = SubResource("Resource_pduds") -id = 3 -type = 2 -building_category = 0 -job_type = 0 -display_name = "Dirt" -default_state = SubResource("Resource_v52p7") -icon = ExtResource("2_6nqfm") -supports_buildings = false -is_ground = false -vertical_speed_multiplier = 2.08165e-12 -horizontal_speed_multiplier = 2.08165e-12 diff --git a/godot/world_objects/objects/dirt_top.tres b/godot/world_objects/objects/dirt_top.tres deleted file mode 100644 index e09358a..0000000 --- a/godot/world_objects/objects/dirt_top.tres +++ /dev/null @@ -1,30 +0,0 @@ -[gd_resource type="Resource" script_class="StaticObject" load_steps=7 format=3 uid="uid://d3jap6lfr1u24"] - -[ext_resource type="Script" path="res://world_objects/types/static/state.gd" id="1_mxbqv"] -[ext_resource type="Texture2D" uid="uid://8f6qgxacftvm" path="res://assets/objects/static/dirt_top.png" id="2_101l4"] -[ext_resource type="Script" path="res://world_objects/types/static/static.gd" id="3_5nln5"] -[ext_resource type="Script" path="res://world_objects/tiles/object_tile.gd" id="4_x43hc"] - -[sub_resource type="Resource" id="Resource_r714b"] -script = ExtResource("1_mxbqv") -id = 0 - -[sub_resource type="Resource" id="Resource_lctn1"] -script = ExtResource("4_x43hc") -texture = ExtResource("2_101l4") -y_offset = 0 - -[resource] -script = ExtResource("3_5nln5") -tile = SubResource("Resource_lctn1") -id = 2 -type = 2 -building_category = 0 -job_type = 0 -display_name = "Dirt" -default_state = SubResource("Resource_r714b") -icon = ExtResource("2_101l4") -supports_buildings = true -is_ground = true -vertical_speed_multiplier = 2.08165e-12 -horizontal_speed_multiplier = 1.0 diff --git a/godot/world_objects/objects/hut.tres b/godot/world_objects/objects/hut.tres deleted file mode 100644 index 48df252..0000000 --- a/godot/world_objects/objects/hut.tres +++ /dev/null @@ -1,48 +0,0 @@ -[gd_resource type="Resource" script_class="BuildingObject" load_steps=10 format=3 uid="uid://cdguvtdn4k47q"] - -[ext_resource type="Script" path="res://world_objects/types/building/states/housing.gd" id="1_pa0b4"] -[ext_resource type="Script" path="res://world_objects/types/building/building.gd" id="1_ysl2l"] -[ext_resource type="Texture2D" uid="uid://cn0let38x5y65" path="res://assets/objects/hut/hut.png" id="2_xyxfs"] -[ext_resource type="Script" path="res://world_objects/tiles/object_tile.gd" id="3_4ajns"] - -[sub_resource type="Resource" id="Resource_oy7g3"] -script = ExtResource("1_pa0b4") -capacity = 0 -habitant_ids = Array[int]([]) -is_active = false -id = 0 - -[sub_resource type="AtlasTexture" id="AtlasTexture_fqgpg"] -atlas = ExtResource("2_xyxfs") -region = Rect2(0, 0, 16, 16) - -[sub_resource type="Resource" id="Resource_87n0e"] -script = ExtResource("3_4ajns") -texture = ExtResource("2_xyxfs") -y_offset = 1 - -[sub_resource type="CompressedTexture2D" id="CompressedTexture2D_0wggt"] -load_path = "res://.godot/imported/hut.png-11e359119cae751511df222a9b16c2c8.ctex" - -[sub_resource type="Resource" id="Resource_j176y"] -script = ExtResource("3_4ajns") -texture = SubResource("CompressedTexture2D_0wggt") -y_offset = 0 - -[resource] -script = ExtResource("1_ysl2l") -tile_ground_inactive = SubResource("Resource_87n0e") -tile_ground_active = SubResource("Resource_87n0e") -tile_up_inactive = SubResource("Resource_j176y") -tile_up_active = SubResource("Resource_j176y") -id = 1 -type = 1 -building_category = 1 -job_type = 0 -display_name = "Hut" -default_state = SubResource("Resource_oy7g3") -icon = SubResource("AtlasTexture_fqgpg") -supports_buildings = true -is_ground = false -vertical_speed_multiplier = 1.0 -horizontal_speed_multiplier = 1.0 diff --git a/godot/world_objects/state.gd b/godot/world_objects/state.gd deleted file mode 100644 index d0649f7..0000000 --- a/godot/world_objects/state.gd +++ /dev/null @@ -1,34 +0,0 @@ -class_name WorldObjectStateDeprecated -extends Resource - -@export var id: WorldObject.ID - -func update(_state: GameStateDepracated, _index: int) -> void: - return - -# What happens when you place this object -func place() -> void: - return - -func get_world_object() -> WorldObject: - if not id is WorldObject.ID: - push_error("Error while trying to retrieve WorldObject: WorldObject id for WorldObjectStateDeprecated '%s' has not been set" % resource_name) - return null - var object: WorldObject = ObjectManager.get_object(id) - if not object is WorldObject: - push_error("Error while trying to retrieve WorldObject: WorldObject for id '%s' does not exist" % WorldObject.get_id_name(id)) - return null - return object - -# Returns the source ID of the tile to be displayed by this object -func get_current_tile() -> WorldObjectTileDeprecated: - push_error("WorldObjectStateDeprecated get_current_tile: Unimplemented for state of id '%s'" % id) - return null - -static func from_dict(_data: Dictionary, _id: int) -> WorldObjectStateDeprecated: - push_error("WorldObjectStateDeprecated Deserialization: Unimplemented for state of id '%s'" % _id) - return null - -func to_dict() -> Dictionary: - push_error("WorldObjectStateDeprecated Serialization: Unimplemented for state of id '%s'" % id) - return {} diff --git a/godot/world_objects/tiles/object_tile.gd b/godot/world_objects/tiles/object_tile.gd deleted file mode 100644 index 9c5a2d7..0000000 --- a/godot/world_objects/tiles/object_tile.gd +++ /dev/null @@ -1,29 +0,0 @@ -class_name WorldObjectTileDeprecated -extends Resource - -@export var texture: Texture2D -@export var y_offset: int = 0 - -# Will be configured when generating the tileset -var source_id: int = 0 - -# The world object state this tile is referring to if it was created as a placeholder -# Important for debugging information -var placeholder_object_state: WorldObjectStateDeprecated - -static func create_placeholder(object_state: WorldObjectStateDeprecated) -> WorldObjectTileDeprecated: - var tile: WorldObjectTileDeprecated = WorldObjectTileDeprecated.new() - tile.placeholder_object_state = object_state - return tile - -func create_source() -> TileSetAtlasSource: - var source: TileSetAtlasSource = TileSetAtlasSource.new() - source.texture = texture - source.create_tile(Vector2i(0, y_offset)) - return source - -func draw_at_coords(tile_map: TileMap, coords: Vector2i) -> void: - tile_map.set_cell(0, coords, source_id, Vector2i(0, y_offset)) - - if placeholder_object_state is WorldObjectStateDeprecated: - push_error("Missing tile texture at cell '%s' for world object id '%s'" % [coords, WorldObject.get_id_name(placeholder_object_state.id)]) diff --git a/godot/world_objects/types/building/building.gd b/godot/world_objects/types/building/building.gd deleted file mode 100644 index 05c1f4e..0000000 --- a/godot/world_objects/types/building/building.gd +++ /dev/null @@ -1,30 +0,0 @@ -class_name BuildingObject -extends WorldObject - -@export var tile_ground_inactive: WorldObjectTileDeprecated -@export var tile_ground_active: WorldObjectTileDeprecated -@export var tile_up_inactive: WorldObjectTileDeprecated -@export var tile_up_active: WorldObjectTileDeprecated - -func _init() -> void: - type = WorldObject.TYPE.BUILDING - -func push_tiles(tileset: TileSet) -> TileSet: - tileset = push_tile(tile_ground_inactive, tileset) - tileset = push_tile(tile_ground_active, tileset) - tileset = push_tile(tile_up_inactive, tileset) - tileset = push_tile(tile_ground_active, tileset) - return tileset - -func new_state_from_dict(data: Dictionary, _id: int) -> WorldObjectStateDeprecated: - var serde_id: String = data.get("s_id") - if not serde_id is String: - push_error("BuldingObjectState Deserialization: Missing serde_id for object state of id '%s'" % _id) - return null - - match serde_id: - "housing": - return HousingBuildingState.from_dict(data, _id) - - push_error("BuildingObjectState Deserialization: Invalid serde_id '%s' for object state of id '%s'" % [serde_id, _id]) - return null diff --git a/godot/world_objects/types/building/state.gd b/godot/world_objects/types/building/state.gd deleted file mode 100644 index 6c2b564..0000000 --- a/godot/world_objects/types/building/state.gd +++ /dev/null @@ -1,28 +0,0 @@ -class_name BuildingObjectState -extends WorldObjectStateDeprecated - -var is_active: bool = false -var is_grounded: bool = false - -func update(state: GameStateDepracated, index: int) -> void: - var grounded_value: int = state.grounded_map.get_value(index) - if grounded_value == 1: - is_grounded = true - else: - is_grounded = false - -func get_current_tile() -> WorldObjectTileDeprecated: - var object: BuildingObject = get_world_object() - if not object is BuildingObject: - push_error("An error occured while retrieving BuildingObject for BuildingObjectState with id '%s': Retrieved object is not of type BuildingObject" % WorldObject.get_id_name(id)) - return null - - if is_active and is_grounded: - return object.tile_ground_active - if is_active and not is_grounded: - return object.tile_up_active - if not is_active and is_grounded: - return object.tile_ground_inactive - if not is_active and not is_grounded: - return object.tile_up_inactive - return null diff --git a/godot/world_objects/types/building/states/housing.gd b/godot/world_objects/types/building/states/housing.gd deleted file mode 100644 index b7f7f06..0000000 --- a/godot/world_objects/types/building/states/housing.gd +++ /dev/null @@ -1,29 +0,0 @@ -class_name HousingBuildingState -extends BuildingObjectState - -@export var capacity: int -@export var habitant_ids: Array[int] = [] - -static func from_dict(data: Dictionary, _id: int) -> HousingBuildingState: - var context: String = "HousingBuildingState" - var _capacity: int = Deserialize.process_int(data, "cpty", context, true, 1) - var _habitant_ids: Array[int] = Deserialize.process_array_int(data, "hb_ids", context) - - var failed: bool = Deserialize.check_for_null([_capacity, _habitant_ids]) - if failed: - push_error("HousingBuildingState Deserialization: Unable to deserialize data") - return null - - var state: HousingBuildingState = HousingBuildingState.new() - state.id = _id - state.capacity = _capacity - state.habitant_ids = _habitant_ids - return state - -func to_dict() -> Dictionary: - var data: Dictionary = {} - data.id = id - data.s_id = "housing" - data.cpty = capacity - data.hb_ids = habitant_ids - return data diff --git a/godot/world_objects/types/static/state.gd b/godot/world_objects/types/static/state.gd deleted file mode 100644 index 3a661f8..0000000 --- a/godot/world_objects/types/static/state.gd +++ /dev/null @@ -1,17 +0,0 @@ -class_name StaticObjectState -extends WorldObjectStateDeprecated - -func get_current_tile() -> WorldObjectTileDeprecated: - var object: StaticObject = get_world_object() - if not object is StaticObject: - push_error("An error occured while retrieving StaticObject for StaticObjectState with id '%s': Retrieved object is not of type StaticObject" % WorldObject.get_id_name(id)) - return null - return object.tile - -static func from_dict(_data: Dictionary, _id: WorldObject.ID) -> StaticObjectState: - var state: StaticObjectState = StaticObjectState.new() - state.id = _id - return state - -func to_dict() -> Dictionary: - return {"id": id} diff --git a/godot/world_objects/types/static/static.gd b/godot/world_objects/types/static/static.gd deleted file mode 100644 index 0ebf9e3..0000000 --- a/godot/world_objects/types/static/static.gd +++ /dev/null @@ -1,14 +0,0 @@ -class_name StaticObject -extends WorldObject - -@export var tile: WorldObjectTileDeprecated - -func _init() -> void: - type = WorldObject.TYPE.STATIC - -func push_tiles(tileset: TileSet) -> TileSet: - tileset = push_tile(tile, tileset) - return tileset - -func new_state_from_dict(_data: Dictionary, _id: int) -> StaticObjectState: - return StaticObjectState.from_dict(_data, _id) diff --git a/rust/main_logic/src/entities/world_object/tile_library.rs b/rust/main_logic/src/entities/tile_library.rs similarity index 100% rename from rust/main_logic/src/entities/world_object/tile_library.rs rename to rust/main_logic/src/entities/tile_library.rs diff --git a/rust/main_logic/src/entities/world_object/behavior.rs b/rust/main_logic/src/entities/world_object/behavior.rs index b628154..a3339ec 100644 --- a/rust/main_logic/src/entities/world_object/behavior.rs +++ b/rust/main_logic/src/entities/world_object/behavior.rs @@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize}; use crate::{ entities::display_tile::DisplayTile, - enums::{tile_type::TileType, world_object_id::WorldObjectId}, + enums::{job_type::JobType, tile_type::TileType, world_object_id::WorldObjectId}, }; use super::{ @@ -15,7 +15,29 @@ use super::{ pub trait WorldObjectBehavior { fn get_id(&self) -> WorldObjectId; fn set_id(&mut self, id: WorldObjectId); - fn get_current_tile_type(&self) -> TileType; + + fn get_housing_capacity(&self) -> u32 { + 0 + } + + fn set_housing_capacity(&mut self, _capacity: u32) {} + + fn get_job_type(&self) -> JobType { + JobType::None + } + + fn set_job_type(&mut self, _job_type: JobType) {} + + fn get_job_production(&self) -> u32 { + 0 + } + + fn set_job_production(&mut self, _job_production: u32) {} + + fn get_current_tile_type(&self) -> TileType { + TileType::None + } + fn get_display_tile(&self, location: Vector2i) -> DisplayTile { DisplayTile { object_id: self.get_id(), @@ -23,11 +45,18 @@ pub trait WorldObjectBehavior { location, } } + fn get_display_tile_gd(&self, location: Vector2i) -> Gd { Gd::from_object(self.get_display_tile(location)) } + fn apply_common_data(&mut self, common_data: Gd) { self.set_id(common_data.bind().id); + self.set_job_type(common_data.bind().job_type) + } + + fn provides_job(&self) -> bool { + self.get_job_type() != JobType::None } } @@ -52,8 +81,18 @@ impl WorldObjectBehaviorType { behavior.get_id() } + pub fn get_job_type(&self) -> JobType { + let behavior = self.get_behavior(); + behavior.get_job_type() + } + pub fn get_display_tile_gd(&self, location: Vector2i) -> Gd { let behavior = self.get_behavior(); behavior.get_display_tile_gd(location) } + + pub fn provides_job(&self) -> bool { + let behavior = self.get_behavior(); + behavior.provides_job() + } } diff --git a/rust/main_logic/src/entities/world_object/behaviors/housing.rs b/rust/main_logic/src/entities/world_object/behaviors/housing.rs index ed73590..dd787d2 100644 --- a/rust/main_logic/src/entities/world_object/behaviors/housing.rs +++ b/rust/main_logic/src/entities/world_object/behaviors/housing.rs @@ -2,13 +2,15 @@ use serde::{Deserialize, Serialize}; use crate::{ entities::world_object::behavior::WorldObjectBehavior, - enums::{tile_type::TileType, world_object_id::WorldObjectId}, + enums::{job_type::JobType, tile_type::TileType, world_object_id::WorldObjectId}, }; #[derive(Serialize, Deserialize, Debug, Default, Clone)] pub struct HousingBehavior { id: WorldObjectId, - pub capacity: u32, + capacity: u32, + job_type: JobType, + job_production: u32, } impl WorldObjectBehavior for HousingBehavior { @@ -20,6 +22,30 @@ impl WorldObjectBehavior for HousingBehavior { self.id = id } + fn get_housing_capacity(&self) -> u32 { + self.capacity + } + + fn set_housing_capacity(&mut self, capacity: u32) { + self.capacity = capacity; + } + + fn get_job_type(&self) -> JobType { + self.job_type + } + + fn set_job_type(&mut self, job_type: JobType) { + self.job_type = job_type + } + + fn get_job_production(&self) -> u32 { + self.job_production + } + + fn set_job_production(&mut self, job_production: u32) { + self.job_production = job_production + } + fn get_current_tile_type(&self) -> TileType { TileType::Persistent } diff --git a/rust/main_logic/src/entities/world_object/collection.rs b/rust/main_logic/src/entities/world_object/collection.rs index d7cc6e6..00c1199 100644 --- a/rust/main_logic/src/entities/world_object/collection.rs +++ b/rust/main_logic/src/entities/world_object/collection.rs @@ -4,20 +4,23 @@ use serde::{Deserialize, Serialize}; use crate::{entities::display_tile::DisplayTile, gamestate::GameState}; use super::behavior::WorldObjectBehaviorType; -use std::collections::HashMap; +use std::{ + collections::HashMap, + sync::{Arc, RwLock}, +}; /// A collection that keeps track of all spawned behavior instances. /// Indexing starts at the top left of the map. -#[derive(Default, Debug, Serialize, Deserialize)] +#[derive(Default, Debug)] pub struct WorldObjectBehaviorCollection { - behaviors: HashMap, + behaviors: Arc>>, } impl WorldObjectBehaviorCollection { pub fn get_current_display_tiles(&self, gamestate: &GameState) -> Array> { let mut array = Array::new(); - - self.behaviors.iter().for_each(|(index, behavior)| { + let behaviors = self.behaviors.read().unwrap(); + behaviors.iter().for_each(|(index, behavior)| { let location = gamestate.index_to_coords(*index); let display_tile = behavior.get_display_tile_gd(location); array.push(display_tile); @@ -27,10 +30,32 @@ impl WorldObjectBehaviorCollection { } pub fn add_at_index(&mut self, index: u32, state: WorldObjectBehaviorType) { - self.behaviors.insert(index, state); + let mut behaviors = self.behaviors.write().unwrap(); + behaviors.insert(index, state); } pub fn is_empty(&self) -> bool { - self.behaviors.is_empty() + self.behaviors.read().unwrap().is_empty() + } +} + +impl Serialize for WorldObjectBehaviorCollection { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + self.behaviors.read().unwrap().serialize(serializer) + } +} + +impl<'de> Deserialize<'de> for WorldObjectBehaviorCollection { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let behaviors = HashMap::deserialize(deserializer)?; + Ok(WorldObjectBehaviorCollection { + behaviors: Arc::new(RwLock::new(behaviors)), + }) } } diff --git a/rust/main_logic/src/entities/world_object/common_data.rs b/rust/main_logic/src/entities/world_object/common_data.rs index b04cc6b..767aae2 100644 --- a/rust/main_logic/src/entities/world_object/common_data.rs +++ b/rust/main_logic/src/entities/world_object/common_data.rs @@ -1,6 +1,6 @@ use godot::prelude::*; -use crate::enums::world_object_id::WorldObjectId; +use crate::enums::{job_type::JobType, world_object_id::WorldObjectId}; /// These are fields that all WorldObjectTemplates have in common /// and will be passed to all new behavior instances @@ -9,4 +9,6 @@ use crate::enums::world_object_id::WorldObjectId; pub struct WorldObjectCommonData { #[export] pub id: WorldObjectId, + #[export] + pub job_type: JobType, } diff --git a/rust/main_logic/src/entities/world_object/factory.rs b/rust/main_logic/src/entities/world_object/factory.rs index 6bb151b..f8f15bf 100644 --- a/rust/main_logic/src/entities/world_object/factory.rs +++ b/rust/main_logic/src/entities/world_object/factory.rs @@ -34,10 +34,12 @@ impl BehaviorFactory { location: Vector2i, common_data: Gd, capacity: u32, + job_production: u32, ) { let mut state = HousingBehavior::default(); state.apply_common_data(common_data); - state.capacity = capacity; + state.set_housing_capacity(capacity); + state.set_job_production(job_production); gamestate .bind_mut() .push_object(location, WorldObjectBehaviorType::Housing(state)) diff --git a/rust/main_logic/src/enums/job_type.rs b/rust/main_logic/src/enums/job_type.rs new file mode 100644 index 0000000..b96cd48 --- /dev/null +++ b/rust/main_logic/src/enums/job_type.rs @@ -0,0 +1,29 @@ +use godot::prelude::*; +use serde::{Deserialize, Serialize}; + +#[derive( + GodotConvert, + Var, + Export, + Debug, + Clone, + Copy, + Serialize, + Deserialize, + PartialEq, + Eq, + PartialOrd, + Ord, + Hash, +)] +#[godot(via = u32)] +pub enum JobType { + None = 0, + Wood = 1, +} + +impl Default for JobType { + fn default() -> Self { + Self::None + } +} diff --git a/rust/main_logic/src/enums/tile_type.rs b/rust/main_logic/src/enums/tile_type.rs index 13d65b5..9193f04 100644 --- a/rust/main_logic/src/enums/tile_type.rs +++ b/rust/main_logic/src/enums/tile_type.rs @@ -18,14 +18,14 @@ use serde::{Deserialize, Serialize}; )] #[godot(via = u32)] pub enum TileType { - None, - Persistent, - Active, - Inactive, - ActiveUp, - ActiveGround, - InactiveUp, - InactiveGround, + None = 0, + Persistent = 1, + Active = 2, + Inactive = 3, + ActiveUp = 4, + ActiveGround = 5, + InactiveUp = 6, + InactiveGround = 7, } impl Default for TileType { diff --git a/rust/main_logic/src/lib.rs b/rust/main_logic/src/lib.rs index b2192ce..d26ef9f 100644 --- a/rust/main_logic/src/lib.rs +++ b/rust/main_logic/src/lib.rs @@ -24,13 +24,14 @@ pub mod entities { pub mod common_data; pub mod factory; pub mod tile; - pub mod tile_library; } pub mod display_tile; pub mod tick_result; + pub mod tile_library; } pub mod enums { + pub mod job_type; pub mod tile_type; pub mod world_object_id; }