DEADSOFTWARE

Add furnace, more craft and items
authorfredboy <fredboy@protonmail.com>
Fri, 10 May 2024 09:56:29 +0000 (16:56 +0700)
committerfredboy <fredboy@protonmail.com>
Fri, 10 May 2024 09:56:29 +0000 (16:56 +0700)
59 files changed:
android/assets/chest.png [new file with mode: 0644]
android/assets/furnace.png [new file with mode: 0644]
android/assets/json/crafting.json
android/assets/json/game_items.json
android/assets/json/texture_regions.json
android/assets/textures/blocks/furnace.png [new file with mode: 0644]
android/assets/textures/blocks/furnace_off.png [deleted file]
android/assets/textures/blocks/furnace_on.png [deleted file]
android/assets/textures/items/bed.png [new file with mode: 0644]
android/assets/textures/items/diamond.png [new file with mode: 0644]
android/assets/textures/items/gold_ingot.png [new file with mode: 0644]
android/assets/textures/items/iron_ingot.png [new file with mode: 0644]
android/assets/textures/items/lapis_lazuli.png [new file with mode: 0644]
android/assets/textures/items/spawn_egg.png [new file with mode: 0644]
android/assets/touch_gui.png
core/src/ru/deadsoftware/cavedroid/game/GameModule.java
core/src/ru/deadsoftware/cavedroid/game/GamePhysics.java
core/src/ru/deadsoftware/cavedroid/game/GameProc.java
core/src/ru/deadsoftware/cavedroid/game/GameRenderer.java
core/src/ru/deadsoftware/cavedroid/game/GameSaver.java
core/src/ru/deadsoftware/cavedroid/game/actions/UseBlockActionsModule.kt
core/src/ru/deadsoftware/cavedroid/game/actions/UseItemActionsModule.kt
core/src/ru/deadsoftware/cavedroid/game/actions/useblock/UseFurnaceAction.kt [new file with mode: 0644]
core/src/ru/deadsoftware/cavedroid/game/actions/useitem/UsePigSpawnEggAction.kt [new file with mode: 0644]
core/src/ru/deadsoftware/cavedroid/game/debug/DebugInfoStringsProvider.kt
core/src/ru/deadsoftware/cavedroid/game/input/MouseInputHandlersModule.kt
core/src/ru/deadsoftware/cavedroid/game/input/handler/keyboard/CloseGameWindowKeyboardInputHandler.kt
core/src/ru/deadsoftware/cavedroid/game/input/handler/keyboard/DropItemKeyboardInputHandler.kt
core/src/ru/deadsoftware/cavedroid/game/input/handler/keyboard/OpenInventoryKeyboardInputHandler.kt
core/src/ru/deadsoftware/cavedroid/game/input/handler/keyboard/PauseGameKeyboardInputHandler.kt
core/src/ru/deadsoftware/cavedroid/game/input/handler/mouse/CloseGameWindowMouseInputHandler.kt
core/src/ru/deadsoftware/cavedroid/game/input/handler/mouse/HotbarMouseInputHandler.kt
core/src/ru/deadsoftware/cavedroid/game/input/handler/mouse/SelectCraftingInventoryItemMouseInputHandler.kt
core/src/ru/deadsoftware/cavedroid/game/input/handler/mouse/SelectFurnaceInventoryItemMouseInputHandler.kt [new file with mode: 0644]
core/src/ru/deadsoftware/cavedroid/game/input/handler/mouse/SelectSurvivalInventoryItemMouseInputHandler.kt
core/src/ru/deadsoftware/cavedroid/game/mobs/player/Inventory.kt
core/src/ru/deadsoftware/cavedroid/game/mobs/player/Player.java
core/src/ru/deadsoftware/cavedroid/game/model/block/Block.kt
core/src/ru/deadsoftware/cavedroid/game/model/dto/ItemDto.kt
core/src/ru/deadsoftware/cavedroid/game/model/item/CommonItemParams.kt
core/src/ru/deadsoftware/cavedroid/game/model/item/InventoryItem.kt
core/src/ru/deadsoftware/cavedroid/game/model/item/Item.kt
core/src/ru/deadsoftware/cavedroid/game/model/mapper/BlockMapper.kt
core/src/ru/deadsoftware/cavedroid/game/model/mapper/ItemMapper.kt
core/src/ru/deadsoftware/cavedroid/game/objects/drop/Drop.kt [moved from core/src/ru/deadsoftware/cavedroid/game/objects/Drop.kt with 96% similarity]
core/src/ru/deadsoftware/cavedroid/game/objects/drop/DropController.java [moved from core/src/ru/deadsoftware/cavedroid/game/objects/DropController.java with 79% similarity]
core/src/ru/deadsoftware/cavedroid/game/objects/furnace/Furnace.kt [new file with mode: 0644]
core/src/ru/deadsoftware/cavedroid/game/objects/furnace/FurnaceController.kt [new file with mode: 0644]
core/src/ru/deadsoftware/cavedroid/game/render/BlocksRenderer.kt
core/src/ru/deadsoftware/cavedroid/game/render/DropsRenderer.kt
core/src/ru/deadsoftware/cavedroid/game/render/WindowsRenderer.kt
core/src/ru/deadsoftware/cavedroid/game/render/windows/FurnaceWindowRenderer.kt [new file with mode: 0644]
core/src/ru/deadsoftware/cavedroid/game/ui/windows/GameWindowsConfigs.kt
core/src/ru/deadsoftware/cavedroid/game/ui/windows/GameWindowsManager.kt
core/src/ru/deadsoftware/cavedroid/game/ui/windows/inventory/FurnaceInventoryWindow.kt [new file with mode: 0644]
core/src/ru/deadsoftware/cavedroid/game/world/GameWorld.java
core/src/ru/deadsoftware/cavedroid/misc/Assets.java
core/src/ru/deadsoftware/cavedroid/misc/utils/MeasureUnitsUtils.kt
core/src/ru/deadsoftware/cavedroid/misc/utils/RenderingUtils.kt

diff --git a/android/assets/chest.png b/android/assets/chest.png
new file mode 100644 (file)
index 0000000..961891f
Binary files /dev/null and b/android/assets/chest.png differ
diff --git a/android/assets/furnace.png b/android/assets/furnace.png
new file mode 100644 (file)
index 0000000..fc04793
Binary files /dev/null and b/android/assets/furnace.png differ
index ddb9a676153b8b5be13fdc17dc5ce5ff5d07d946..837a977e0bb7b56cbb7cd3ab26ed0b1d099bf77a 100644 (file)
     "input": ["cobblestone", "none", "none", "stick", "none", "none", "stick", "none", "none"],
     "count": 131
   },
+  "iron_pickaxe": {
+    "input": ["iron_ingot", "iron_ingot", "iron_ingot", "none", "stick", "none", "none", "stick", "none"],
+    "count": 251
+  },
+  "iron_axe": {
+    "input": ["iron_ingot", "iron_ingot", "none", "iron_ingot", "stick", "none", "none", "stick", "none"],
+    "count": 250
+  },
+  "iron_sword": {
+    "input": ["iron_ingot", "none", "none", "iron_ingot", "none", "none", "stick", "none", "none"],
+    "count": 251
+  },
+  "iron_shovel": {
+    "input": ["iron_ingot", "none", "none", "stick", "none", "none", "stick", "none", "none"],
+    "count": 250
+  },
+  "gold_pickaxe": {
+    "input": ["gold_ingot", "gold_ingot", "gold_ingot", "none", "stick", "none", "none", "stick", "none"],
+    "count": 33
+  },
+  "gold_axe": {
+    "input": ["gold_ingot", "gold_ingot", "none", "gold_ingot", "stick", "none", "none", "stick", "none"],
+    "count": 32
+  },
+  "gold_sword": {
+    "input": ["gold_ingot", "none", "none", "gold_ingot", "none", "none", "stick", "none", "none"],
+    "count": 33
+  },
+  "gold_shovel": {
+    "input": ["gold_ingot", "none", "none", "stick", "none", "none", "stick", "none", "none"],
+    "count": 32
+  },
+  "diamond_pickaxe": {
+    "input": ["diamond", "diamond", "diamond", "none", "stick", "none", "none", "stick", "none"],
+    "count": 1562
+  },
+  "diamond_axe": {
+    "input": ["diamond", "diamond", "none", "diamond", "stick", "none", "none", "stick", "none"],
+    "count": 1561
+  },
+  "diamond_sword": {
+    "input": ["diamond", "none", "none", "diamond", "none", "none", "stick", "none", "none"],
+    "count": 1562
+  },
+  "diamond_shovel": {
+    "input": ["diamond", "none", "none", "stick", "none", "none", "stick", "none", "none"],
+    "count": 1561
+  },
   "snow_block": {
     "input": ["snowball", "snowball", "none", "snowball", "snowball", "none", "none", "none", "none"],
     "count": 1
   },
   "crafting_table": {
     "input": ["planks.*", "planks.*", "none", "planks.*", "planks.*", "none", "none", "none", "none"]
+  },
+  "furnace": {
+    "input": ["cobblestone", "cobblestone", "cobblestone", "cobblestone", "none", "cobblestone", "cobblestone", "cobblestone", "cobblestone"]
   }
 }
\ No newline at end of file
index d8523b9672dc7cf536ff1d9f6a8f0079175528e7..77493459c2bfaded590e57a0a959d577014b2799 100644 (file)
       "hp": 60,
       "tool_level": 1,
       "tool_type": "shovel"
+    },
+    "furnace": {
+      "hp": 1050,
+      "collision": true,
+      "transparent": false,
+      "drop": "furnace",
+      "texture": "furnace",
+      "animated": true,
+      "frames": 2,
+      "tool_level": 1,
+      "tool_type": "pickaxe",
+      "meta": "furnace"
     }
   },
   "items": {
     "cobblestone": {
       "name": "Cobblestone",
       "type": "block",
-      "texture": "cobblestone"
+      "texture": "cobblestone",
+      "smelt_product": "stone"
     },
     "planks_oak": {
       "name": "Oak Planks",
       "type": "block",
-      "texture": "planks_oak"
+      "texture": "planks_oak",
+      "burning_time": 15000
     },
     "sapling_oak": {
       "name": "Oak Sapling",
       "type": "block",
-      "texture": "sapling_oak"
+      "texture": "sapling_oak",
+      "burning_time": 5000
     },
     "planks_spruce": {
       "name": "Spruce Planks",
       "type": "block",
-      "texture": "planks_spruce"
+      "texture": "planks_spruce",
+      "burning_time": 15000
     },
     "crafting_table": {
       "name": "Crafting Table",
       "type": "block",
-      "texture": "crafting_table"
+      "texture": "crafting_table",
+      "burning_time": 15000
+    },
+    "furnace": {
+      "name": "Furnace",
+      "type": "block",
+      "texture": "furnace_off"
     },
     "sapling_spruce": {
       "name": "Spruce Sapling",
       "type": "block",
-      "texture": "sapling_spruce"
+      "texture": "sapling_spruce",
+      "burning_time": 5000
     },
     "bedrock": {
       "name": "Bedrock",
     "sand": {
       "name": "Sand",
       "type": "block",
-      "texture": "sand"
+      "texture": "sand",
+      "smelt_product": "glass"
     },
     "gravel": {
       "name": "Gravel",
     "gold_ore": {
       "name": "Golden Ore",
       "type": "block",
-      "texture": "gold_ore"
+      "texture": "gold_ore",
+      "smelt_product": "gold_ingot"
     },
     "iron_ore": {
       "name": "Iron Ore",
       "type": "block",
-      "texture": "iron_ore"
+      "texture": "iron_ore",
+      "smelt_product": "iron_ingot"
     },
     "coal_ore": {
       "name": "Coal Ore",
       "type": "block",
-      "texture": "coal_ore"
+      "texture": "coal_ore",
+      "smelt_product": "coal"
     },
     "diamond_ore": {
       "name": "Diamond Ore",
       "type": "block",
-      "texture": "diamond_ore"
+      "texture": "diamond_ore",
+      "smelt_product": "diamond"
     },
     "log_oak": {
       "name": "Wood",
       "type": "block",
-      "texture": "log_oak"
+      "texture": "log_oak",
+      "burning_time": 15000,
+      "smelt_product": "charcoal"
     },
     "leaves_oak": {
       "name": "Leaves",
     "log_spruce": {
       "name": "Spruce",
       "type": "block",
-      "texture": "log_spruce"
+      "texture": "log_spruce",
+      "burning_time": 15000,
+      "smelt_product": "charcoal"
     },
     "leaves_spruce": {
       "name": "Spruce Leaves",
     "lapis_ore": {
       "name": "Lapis Ore",
       "type": "block",
-      "texture": "lapis_ore"
+      "texture": "lapis_ore",
+      "smelt_product": "lapis_lazuli"
     },
     "lapis_block": {
       "name": "Lapis Block",
       "name": "Dead Bush",
       "type": "block",
       "texture": "deadbush",
-      "origin_x": 0.5
+      "origin_x": 0.5,
+      "burning_time": 5000
     },
     "bricks": {
       "name": "Bricks",
       "type": "slab",
       "texture": "oak_slab",
       "top_slab_block": "oak_slab_top",
-      "bottom_slab_block": "oak_slab_bottom"
+      "bottom_slab_block": "oak_slab_bottom",
+      "burn_time": 7500
     },
     "spruce_slab": {
       "name": "Spruce Slab",
       "type": "slab",
       "texture": "spruce_slab",
       "top_slab_block": "spruce_slab_top",
-      "bottom_slab_block": "spruce_slab_bottom"
+      "bottom_slab_block": "spruce_slab_bottom",
+      "burn_time": 7500
     },
     "cobblestone_slab": {
       "name": "Cobblestone Slab",
     },
     "stick": {
       "name": "Stick",
-      "texture": "stick"
+      "texture": "stick",
+      "burning_time": 5000
     },
     "wood_sword": {
       "name": "Wooden Sword",
       "texture": "wood_sword",
       "origin_x": 0.125,
       "tool_level": 1,
-      "max_stack": 60
+      "max_stack": 60,
+      "burning_time": 10000
     },
     "stone_sword": {
       "name": "Stone Sword",
       "texture": "wood_pickaxe",
       "origin_x": 0.125,
       "tool_level" : 1,
-      "max_stack": 59
+      "max_stack": 59,
+      "burning_time": 10000
     },
     "stone_pickaxe": {
       "name": "Stone Pickaxe",
       "texture": "wood_axe",
       "origin_x": 0.125,
       "tool_level" : 1,
-      "max_stack": 60
+      "max_stack": 60,
+      "burning_time": 10000
     },
     "stone_axe": {
       "name": "Stone Axe",
     },
     "bucket_empty": {
       "name": "Empty Bucket",
-      "type": "bucket",
+      "type": "usable",
       "texture": "bucket_empty",
       "origin_x": 0.25,
       "action_key": "use_empty_bucket",
     },
     "bucket_water": {
       "name": "Water Bucket",
-      "type": "bucket",
+      "type": "usable",
       "texture": "bucket_water",
       "origin_x": 0.25,
       "action_key": "use_water_bucket",
     },
     "bucket_lava": {
       "name": "Lava Bucket",
-      "type": "bucket",
+      "type": "usable",
       "texture": "bucket_lava",
       "origin_x": 0.25,
       "action_key": "use_lava_bucket",
-      "max_stack": 1
+      "max_stack": 1,
+      "burning_time": 1000000
     },
     "snowball": {
       "name": "Snowball",
+      "type": "usable",
       "texture": "snowball",
+      "action_key": "use_snow_ball_action",
       "max_stack": 16
+    },
+    "coal": {
+      "name": "Coal",
+      "texture": "coal",
+      "burning_time": 80000,
+      "origin_x": 0.25
+    },
+    "charcoal": {
+      "name": "Charcoal",
+      "texture": "charcoal",
+      "burning_time": 80000,
+      "origin_x": 0.25
+    },
+    "iron_ingot": {
+      "name": "Iron Ingot",
+      "texture": "iron_ingot",
+      "origin_x": 0.5
+    },
+    "gold_ingot": {
+      "name": "Gold Ingot",
+      "texture": "gold_ingot",
+      "origin_x": 0.5
+    },
+    "diamond": {
+      "name": "Diamond",
+      "texture": "diamond",
+      "origin_x": 0.5
+    },
+    "lapis_lazuli": {
+      "name": "Lapis Lazuli",
+      "texture": "lapis_lazuli",
+      "origin_x": 0.5
+    },
+    "bed": {
+      "name": "Bed",
+      "type": "usable",
+      "texture": "bed",
+      "action_key": "use_bed_action"
+    },
+    "spawn_egg_pig": {
+      "name": "Pig Spawn Egg",
+      "type": "usable",
+      "texture": "spawn_egg",
+      "tint": "#EDBFB4",
+      "action_key": "use_spawn_egg_pig",
+      "origin_x": 0.5
     }
   }
 }
index 11459c3b2c601bfdd5ad98f15c7e98d0e492dbba..1800acda7225565dd9241f9fed465bda20a55821 100644 (file)
       "h": 166
     }
   },
+  "furnace": {
+    "furnace": {
+      "w": 176,
+      "h": 166
+    },
+    "furnace_burn": {
+      "x": 176,
+      "w": 14,
+      "h": 14
+    },
+    "furnace_progress": {
+      "x": 176,
+      "y": 14,
+      "w": 24,
+      "h": 14
+    }
+  },
   "buttons": {
     "button_0": {
       "w": 200,
diff --git a/android/assets/textures/blocks/furnace.png b/android/assets/textures/blocks/furnace.png
new file mode 100644 (file)
index 0000000..080d8ad
Binary files /dev/null and b/android/assets/textures/blocks/furnace.png differ
diff --git a/android/assets/textures/blocks/furnace_off.png b/android/assets/textures/blocks/furnace_off.png
deleted file mode 100644 (file)
index 6d9b405..0000000
Binary files a/android/assets/textures/blocks/furnace_off.png and /dev/null differ
diff --git a/android/assets/textures/blocks/furnace_on.png b/android/assets/textures/blocks/furnace_on.png
deleted file mode 100644 (file)
index ecbc607..0000000
Binary files a/android/assets/textures/blocks/furnace_on.png and /dev/null differ
diff --git a/android/assets/textures/items/bed.png b/android/assets/textures/items/bed.png
new file mode 100644 (file)
index 0000000..0e1565d
Binary files /dev/null and b/android/assets/textures/items/bed.png differ
diff --git a/android/assets/textures/items/diamond.png b/android/assets/textures/items/diamond.png
new file mode 100644 (file)
index 0000000..eff11e0
Binary files /dev/null and b/android/assets/textures/items/diamond.png differ
diff --git a/android/assets/textures/items/gold_ingot.png b/android/assets/textures/items/gold_ingot.png
new file mode 100644 (file)
index 0000000..b159455
Binary files /dev/null and b/android/assets/textures/items/gold_ingot.png differ
diff --git a/android/assets/textures/items/iron_ingot.png b/android/assets/textures/items/iron_ingot.png
new file mode 100644 (file)
index 0000000..1ff5c69
Binary files /dev/null and b/android/assets/textures/items/iron_ingot.png differ
diff --git a/android/assets/textures/items/lapis_lazuli.png b/android/assets/textures/items/lapis_lazuli.png
new file mode 100644 (file)
index 0000000..84bdcd4
Binary files /dev/null and b/android/assets/textures/items/lapis_lazuli.png differ
diff --git a/android/assets/textures/items/spawn_egg.png b/android/assets/textures/items/spawn_egg.png
new file mode 100644 (file)
index 0000000..8733a83
Binary files /dev/null and b/android/assets/textures/items/spawn_egg.png differ
index 62e4af5df547863ce2cb1ea1462b20073b347a96..57dffc457a9ed27fa82a208a71a0f5deb0922c9a 100644 (file)
Binary files a/android/assets/touch_gui.png and b/android/assets/touch_gui.png differ
index fbbd294b0e032dda43c29c6ce772303a83673c1f..2385230df15533a680a84a871a487f0e71642cf6 100644 (file)
@@ -5,7 +5,8 @@ import dagger.Provides;
 import ru.deadsoftware.cavedroid.MainConfig;
 import ru.deadsoftware.cavedroid.game.mobs.MobsController;
 import ru.deadsoftware.cavedroid.game.model.block.Block;
-import ru.deadsoftware.cavedroid.game.objects.DropController;
+import ru.deadsoftware.cavedroid.game.objects.drop.DropController;
+import ru.deadsoftware.cavedroid.game.objects.furnace.FurnaceController;
 import ru.deadsoftware.cavedroid.game.ui.TooltipManager;
 import ru.deadsoftware.cavedroid.game.world.GameWorld;
 
@@ -43,6 +44,16 @@ public class GameModule {
         return controller;
     }
 
+    @Provides
+    @GameScope
+    public static FurnaceController provideFurnaceController(MainConfig mainConfig, GameItemsHolder gameItemsHolder) {
+        load(mainConfig, gameItemsHolder);
+        FurnaceController controller = data != null ? data.retrueveFurnaceController() : new FurnaceController();
+        makeDataNullIfEmpty();
+        controller.init(gameItemsHolder);
+        return controller;
+    }
+
     @Provides
     @GameScope
     public static MobsController provideMobsController(MainConfig mainConfig,
@@ -62,12 +73,13 @@ public class GameModule {
     public static GameWorld provideGameWorld(MainConfig mainConfig,
                                              DropController dropController,
                                              MobsController mobsController,
-                                             GameItemsHolder gameItemsHolder) {
+                                             GameItemsHolder gameItemsHolder,
+                                             FurnaceController furnaceController) {
         load(mainConfig, gameItemsHolder);
         Block[][] fm = data != null ? data.retrieveForeMap() : null;
         Block[][] bm = data != null ? data.retrieveBackMap() : null;
         makeDataNullIfEmpty();
-        return new GameWorld(dropController, mobsController, gameItemsHolder, fm, bm);
+        return new GameWorld(dropController, mobsController, gameItemsHolder, furnaceController, fm, bm);
     }
 
 }
index eee83c747ab915f41570455f4add9854d70877db..aebf8eb654eb03b7865162b6ec721557c1eddb5c 100644 (file)
@@ -9,8 +9,8 @@ import ru.deadsoftware.cavedroid.game.mobs.Mob;
 import ru.deadsoftware.cavedroid.game.mobs.MobsController;
 import ru.deadsoftware.cavedroid.game.mobs.player.Player;
 import ru.deadsoftware.cavedroid.game.model.block.Block;
-import ru.deadsoftware.cavedroid.game.objects.Drop;
-import ru.deadsoftware.cavedroid.game.objects.DropController;
+import ru.deadsoftware.cavedroid.game.objects.drop.Drop;
+import ru.deadsoftware.cavedroid.game.objects.drop.DropController;
 import ru.deadsoftware.cavedroid.game.world.GameWorld;
 
 import javax.annotation.CheckForNull;
index d797680d8dad99036c528ab620360a86542e0c28..a3fcabbbf4ccfd65466d78e83e46fea7ce428266 100644 (file)
@@ -6,6 +6,7 @@ import com.badlogic.gdx.utils.Timer;
 import ru.deadsoftware.cavedroid.MainConfig;
 import ru.deadsoftware.cavedroid.game.mobs.MobsController;
 import ru.deadsoftware.cavedroid.game.mobs.player.Player;
+import ru.deadsoftware.cavedroid.game.objects.furnace.FurnaceController;
 import ru.deadsoftware.cavedroid.game.world.GameWorldBlocksLogicControllerTask;
 import ru.deadsoftware.cavedroid.game.world.GameWorldFluidsLogicControllerTask;
 import ru.deadsoftware.cavedroid.game.world.GameWorldMobDamageControllerTask;
@@ -18,6 +19,8 @@ public class GameProc implements Disposable {
     private final GamePhysics mGamePhysics;
     private final GameRenderer mGameRenderer;
     private final MobsController mMobsController;
+    private final FurnaceController mFurnaceController;
+    private final GameItemsHolder mGameItemsHolder;
     private final GameWorldFluidsLogicControllerTask mGameWorldFluidsLogicControllerTask;
     private final GameWorldBlocksLogicControllerTask mGameWorldBlocksLogicControllerTask;
     private final GameWorldMobDamageControllerTask mGameWorldMobDamageControllerTask;
@@ -29,6 +32,8 @@ public class GameProc implements Disposable {
                     GamePhysics gamePhysics,
                     GameRenderer gameRenderer,
                     MobsController mobsController,
+                    FurnaceController furnaceController,
+                    GameItemsHolder gameItemsHolder,
                     GameWorldFluidsLogicControllerTask gameWorldFluidsLogicControllerTask,
                     GameWorldBlocksLogicControllerTask gameWorldBlocksLogicControllerTask,
                     GameWorldMobDamageControllerTask gameWorldMobDamageControllerTask
@@ -36,6 +41,8 @@ public class GameProc implements Disposable {
         mGamePhysics = gamePhysics;
         mGameRenderer = gameRenderer;
         mMobsController = mobsController;
+        mFurnaceController = furnaceController;
+        mGameItemsHolder = gameItemsHolder;
         mGameWorldFluidsLogicControllerTask = gameWorldFluidsLogicControllerTask;
         mGameWorldBlocksLogicControllerTask = gameWorldBlocksLogicControllerTask;
         mGameWorldMobDamageControllerTask = gameWorldMobDamageControllerTask;
@@ -57,6 +64,7 @@ public class GameProc implements Disposable {
     public void update(float delta) {
         mGamePhysics.update(delta);
         mGameRenderer.render(delta);
+        mFurnaceController.update(mGameItemsHolder);
     }
 
     public void show() {
index 36f6c75aadbe64eb4de8115db837ba7de59a8d35..2ae4756f54ab06b08b1c309ca3330348f4726d3c 100644 (file)
@@ -109,7 +109,9 @@ public class GameRenderer extends Renderer {
 
         float camTargetX, camTargetY;
 
-        if (player.controlMode == Player.ControlMode.WALK) {
+        boolean followPlayer = player.controlMode == Player.ControlMode.WALK || !mMainConfig.isTouch();
+
+        if (followPlayer) {
             camTargetX = plTargetX + Math.min(player.getVelocity().x * 2, getWidth() / 2);
             camTargetY = plTargetY + player.getVelocity().y;
         } else {
@@ -119,7 +121,7 @@ public class GameRenderer extends Renderer {
 
         Vector2 moveVector = new Vector2(camTargetX - camCenterX, camTargetY - camCenterY);
 
-        if (player.controlMode == Player.ControlMode.WALK && player.getVelocity().isZero()) {
+        if (followPlayer && player.getVelocity().isZero()) {
             mCameraDelayMs = TimeUtils.millis();
             mCamCenterToPlayer.x = plTargetX - camCenterX;
             mCamCenterToPlayer.y = plTargetY - camCenterY;
index cb52b3c76b126812e355c43d9ce076c7d5749140..dd1618640957ce3bbb200a7f509145daad838674 100644 (file)
@@ -5,7 +5,8 @@ import com.badlogic.gdx.files.FileHandle;
 import ru.deadsoftware.cavedroid.MainConfig;
 import ru.deadsoftware.cavedroid.game.mobs.MobsController;
 import ru.deadsoftware.cavedroid.game.model.block.Block;
-import ru.deadsoftware.cavedroid.game.objects.DropController;
+import ru.deadsoftware.cavedroid.game.objects.drop.DropController;
+import ru.deadsoftware.cavedroid.game.objects.furnace.FurnaceController;
 import ru.deadsoftware.cavedroid.game.world.GameWorld;
 
 import javax.annotation.CheckForNull;
@@ -24,11 +25,18 @@ public class GameSaver {
         @CheckForNull
         private DropController mDropController;
         @CheckForNull
+        private FurnaceController mFurnaceController;
+        @CheckForNull
         private Block[][] mForeMap, mBackMap;
 
-        public Data(MobsController mobsController, DropController dropController, Block[][] foreMap, Block[][] backMap) {
+        public Data(MobsController mobsController,
+                    DropController dropController,
+                    FurnaceController furnaceController,
+                    Block[][] foreMap,
+                    Block[][] backMap) {
             mMobsController = mobsController;
             mDropController = dropController;
+            mFurnaceController = furnaceController;
             mForeMap = foreMap;
             mBackMap = backMap;
         }
@@ -47,6 +55,13 @@ public class GameSaver {
             return dropController;
         }
 
+        public FurnaceController retrueveFurnaceController() {
+            assert mFurnaceController != null;
+            FurnaceController furnaceController = mFurnaceController;
+            mFurnaceController = null;
+            return furnaceController;
+        }
+
         public Block[][] retrieveForeMap() {
             assert mForeMap != null;
             Block[][] foreMap = mForeMap;
@@ -183,10 +198,12 @@ public class GameSaver {
             int version = in.readInt();
             DropController dropController;
             MobsController mobsController;
+            FurnaceController furnaceController;
 
             if (SAVE_VERSION == version) {
                 dropController = (DropController) in.readObject();
                 mobsController = (MobsController) in.readObject();
+                furnaceController = (FurnaceController) in.readObject();
             } else {
                 throw new Exception("version mismatch");
             }
@@ -201,7 +218,7 @@ public class GameSaver {
                 throw new Exception("couldn't load");
             }
 
-            return new Data(mobsController, dropController, foreMap, backMap);
+            return new Data(mobsController, dropController, furnaceController, foreMap, backMap);
         } catch (Exception e) {
             Gdx.app.error("GameSaver", e.getMessage());
         }
@@ -212,6 +229,7 @@ public class GameSaver {
     public static void save(MainConfig mainConfig,
                             DropController dropController,
                             MobsController mobsController,
+                            FurnaceController furnaceController,
                             GameWorld gameWorld) {
         String folder = mainConfig.getGameFolder();
         FileHandle file = Gdx.files.absolute(folder + "/saves/");
@@ -229,6 +247,7 @@ public class GameSaver {
             out.writeInt(SAVE_VERSION);
             out.writeObject(dropController);
             out.writeObject(mobsController);
+            out.writeObject(furnaceController);
             out.close();
 
             saveDict(Gdx.files.absolute(folder + "/saves/dict"), dict);
index 76127fa4226d2deee0c1f6c124c84bec08f3379b..5b2a169018564609c38a9741a675b85b4d6f7d9c 100644 (file)
@@ -7,6 +7,7 @@ import dagger.multibindings.StringKey
 import ru.deadsoftware.cavedroid.game.GameScope
 import ru.deadsoftware.cavedroid.game.actions.useblock.IUseBlockAction
 import ru.deadsoftware.cavedroid.game.actions.useblock.UseCraftingTableAction
+import ru.deadsoftware.cavedroid.game.actions.useblock.UseFurnaceAction
 
 @Module
 class UseBlockActionsModule {
@@ -18,4 +19,12 @@ class UseBlockActionsModule {
     fun bindUseCraftingTableAction(action: UseCraftingTableAction): IUseBlockAction {
         return action
     }
+
+    @Binds
+    @IntoMap
+    @StringKey(UseFurnaceAction.KEY)
+    @GameScope
+    fun bindUseFurnaceTableAction(action: UseFurnaceAction): IUseBlockAction {
+        return action
+    }
 }
index 0206d5f82fe9c0fb61511d45e662a7dd1e8456ec..a6aed22cfdc04b1f696efa4cb0e449247ec81380 100644 (file)
@@ -34,4 +34,12 @@ class UseItemActionsModule {
         return action
     }
 
+    @Binds
+    @IntoMap
+    @StringKey(UsePigSpawnEggAction.ACTION_KEY)
+    @GameScope
+    fun bindUsePigSpawnEgg(action: UsePigSpawnEggAction): IUseItemAction {
+        return action
+    }
+
 }
diff --git a/core/src/ru/deadsoftware/cavedroid/game/actions/useblock/UseFurnaceAction.kt b/core/src/ru/deadsoftware/cavedroid/game/actions/useblock/UseFurnaceAction.kt
new file mode 100644 (file)
index 0000000..88a6a7f
--- /dev/null
@@ -0,0 +1,23 @@
+package ru.deadsoftware.cavedroid.game.actions.useblock
+
+import ru.deadsoftware.cavedroid.game.GameScope
+import ru.deadsoftware.cavedroid.game.model.block.Block
+import ru.deadsoftware.cavedroid.game.objects.furnace.FurnaceController
+import ru.deadsoftware.cavedroid.game.ui.windows.GameWindowsManager
+import javax.inject.Inject
+
+@GameScope
+class UseFurnaceAction @Inject constructor(
+    private val furnaceController: FurnaceController,
+    private val gameWindowsManager: GameWindowsManager,
+) : IUseBlockAction {
+
+    override fun perform(block: Block, x: Int, y: Int) {
+        val furnace = furnaceController.getFurnace(x, y, 0) ?: furnaceController.getFurnace(x, y, 1) ?: return
+        gameWindowsManager.openFurnace(furnace)
+    }
+
+    companion object {
+        const val KEY = "furnace"
+    }
+}
\ No newline at end of file
diff --git a/core/src/ru/deadsoftware/cavedroid/game/actions/useitem/UsePigSpawnEggAction.kt b/core/src/ru/deadsoftware/cavedroid/game/actions/useitem/UsePigSpawnEggAction.kt
new file mode 100644 (file)
index 0000000..0c50d15
--- /dev/null
@@ -0,0 +1,27 @@
+package ru.deadsoftware.cavedroid.game.actions.useitem
+
+import ru.deadsoftware.cavedroid.game.GameScope
+import ru.deadsoftware.cavedroid.game.mobs.MobsController
+import ru.deadsoftware.cavedroid.game.mobs.Pig
+import ru.deadsoftware.cavedroid.game.model.item.Item
+import ru.deadsoftware.cavedroid.misc.utils.px
+import javax.inject.Inject
+
+@GameScope
+class UsePigSpawnEggAction @Inject constructor(
+    private val mobsController: MobsController,
+) : IUseItemAction {
+
+    override fun perform(item: Item.Usable, x: Int, y: Int) {
+        Pig(mobsController.player.cursorX.px, mobsController.player.cursorY.px)
+            .apply {
+                attachToController(mobsController)
+            }
+
+        mobsController.player.inventory.decreaseCurrentItemAmount()
+    }
+
+    companion object {
+        const val ACTION_KEY = "use_spawn_egg_pig"
+    }
+}
index 0886a0756f7a54a829edb8ad6769cb1b59f6bc3b..df1dd06e2e705643b0c71456192e420f75f8989a 100644 (file)
@@ -3,7 +3,7 @@ package ru.deadsoftware.cavedroid.game.debug
 import com.badlogic.gdx.Gdx
 import ru.deadsoftware.cavedroid.game.GameScope
 import ru.deadsoftware.cavedroid.game.mobs.MobsController
-import ru.deadsoftware.cavedroid.game.objects.DropController
+import ru.deadsoftware.cavedroid.game.objects.drop.DropController
 import ru.deadsoftware.cavedroid.game.world.GameWorld
 import javax.inject.Inject
 
index 3d5f32ac0c08b5632c2ce93677c2c1b6060110a0..fe9bba635138f3b6e31a591ca3c5e48f1e3ce7a2 100644 (file)
@@ -74,6 +74,13 @@ object MouseInputHandlersModule {
         return handler
     }
 
+    @Binds
+    @IntoSet
+    @GameScope
+    fun bindSelectFurnaceInventoryItemMouseInputHandler(handler: SelectFurnaceInventoryItemMouseInputHandler): IGameInputHandler<MouseInputAction> {
+        return handler
+    }
+
     @Binds
     @IntoSet
     @GameScope
index 6a8f019f68dd70e17b0bac61fdbd0a58b6c1e63b..89a7b693c02492243440ca4385805bc462e47924 100644 (file)
@@ -6,7 +6,7 @@ import ru.deadsoftware.cavedroid.game.input.IGameInputHandler
 import ru.deadsoftware.cavedroid.game.input.action.KeyboardInputAction
 import ru.deadsoftware.cavedroid.game.input.action.keys.KeyboardInputActionKey
 import ru.deadsoftware.cavedroid.game.mobs.MobsController
-import ru.deadsoftware.cavedroid.game.objects.DropController
+import ru.deadsoftware.cavedroid.game.objects.drop.DropController
 import ru.deadsoftware.cavedroid.game.ui.windows.GameWindowsManager
 import javax.inject.Inject
 
index b46812c31fa31baf1792f554d8cb423825515578..04f5520af367a3123bb331181e265dc20aaf0855 100644 (file)
@@ -7,8 +7,8 @@ import ru.deadsoftware.cavedroid.game.input.action.KeyboardInputAction
 import ru.deadsoftware.cavedroid.game.input.action.keys.KeyboardInputActionKey
 import ru.deadsoftware.cavedroid.game.mobs.MobsController
 import ru.deadsoftware.cavedroid.game.model.item.Item
-import ru.deadsoftware.cavedroid.game.objects.Drop
-import ru.deadsoftware.cavedroid.game.objects.DropController
+import ru.deadsoftware.cavedroid.game.objects.drop.Drop
+import ru.deadsoftware.cavedroid.game.objects.drop.DropController
 import ru.deadsoftware.cavedroid.game.ui.windows.GameWindowsManager
 import javax.inject.Inject
 
index ce7005408993aa621528c48a280ad77e4864b29f..ec8190a40c2a3902888a404463ab5fc0e0eb9d03 100644 (file)
@@ -5,8 +5,6 @@ import ru.deadsoftware.cavedroid.game.GameUiWindow
 import ru.deadsoftware.cavedroid.game.input.IGameInputHandler
 import ru.deadsoftware.cavedroid.game.input.action.KeyboardInputAction
 import ru.deadsoftware.cavedroid.game.input.action.keys.KeyboardInputActionKey
-import ru.deadsoftware.cavedroid.game.mobs.MobsController
-import ru.deadsoftware.cavedroid.game.objects.DropController
 import ru.deadsoftware.cavedroid.game.ui.windows.GameWindowsManager
 import javax.inject.Inject
 
index 60a9edfdcaacfb015da3a7ee79e05367e8b8c80c..8ba35c1d87c82695a4c208338dd44a0d563a75a9 100644 (file)
@@ -7,7 +7,8 @@ import ru.deadsoftware.cavedroid.game.input.IGameInputHandler
 import ru.deadsoftware.cavedroid.game.input.action.KeyboardInputAction
 import ru.deadsoftware.cavedroid.game.input.action.keys.KeyboardInputActionKey
 import ru.deadsoftware.cavedroid.game.mobs.MobsController
-import ru.deadsoftware.cavedroid.game.objects.DropController
+import ru.deadsoftware.cavedroid.game.objects.drop.DropController
+import ru.deadsoftware.cavedroid.game.objects.furnace.FurnaceController
 import ru.deadsoftware.cavedroid.game.world.GameWorld
 import javax.inject.Inject
 
@@ -17,6 +18,7 @@ class PauseGameKeyboardInputHandler @Inject constructor(
     private val dropController: DropController,
     private val mobsController: MobsController,
     private val gameWorld: GameWorld,
+    private val furnaceController: FurnaceController,
 ) : IGameInputHandler<KeyboardInputAction> {
 
     override fun checkConditions(action: KeyboardInputAction): Boolean {
@@ -24,7 +26,7 @@ class PauseGameKeyboardInputHandler @Inject constructor(
     }
 
     override fun handle(action: KeyboardInputAction) {
-        GameSaver.save(mainConfig, dropController, mobsController, gameWorld)
+        GameSaver.save(mainConfig, dropController, mobsController, furnaceController, gameWorld)
         mainConfig.caveGame.quitGame()
     }
 }
\ No newline at end of file
index ffda344c1e25863926cc9e1bf8ae780cfbec2b45..ddc41e268613e2dd6129f5892e187be04e5e8df3 100644 (file)
@@ -9,7 +9,7 @@ import ru.deadsoftware.cavedroid.game.input.action.MouseInputAction
 import ru.deadsoftware.cavedroid.game.input.action.keys.MouseInputActionKey
 import ru.deadsoftware.cavedroid.game.input.isInsideWindow
 import ru.deadsoftware.cavedroid.game.mobs.MobsController
-import ru.deadsoftware.cavedroid.game.objects.DropController
+import ru.deadsoftware.cavedroid.game.objects.drop.DropController
 import ru.deadsoftware.cavedroid.misc.Assets
 import javax.inject.Inject
 
@@ -23,6 +23,7 @@ class CloseGameWindowMouseInputHandler @Inject constructor(
     private val creativeInventoryTexture get() = requireNotNull(Assets.textureRegions["creative"])
     private val survivalInventoryTexture get() = requireNotNull(Assets.textureRegions["survival"])
     private val craftingInventoryTexture get() = requireNotNull(Assets.textureRegions["crafting_table"])
+    private val furnaceInventoryTexture get() = requireNotNull(Assets.textureRegions["furnace"])
 
     override fun checkConditions(action: MouseInputAction): Boolean {
         return gameWindowsManager.getCurrentWindow() != GameUiWindow.NONE &&
@@ -36,6 +37,7 @@ class CloseGameWindowMouseInputHandler @Inject constructor(
             GameUiWindow.CREATIVE_INVENTORY -> creativeInventoryTexture
             GameUiWindow.SURVIVAL_INVENTORY -> survivalInventoryTexture
             GameUiWindow.CRAFTING_TABLE -> craftingInventoryTexture
+            GameUiWindow.FURNACE -> furnaceInventoryTexture
             else -> throw UnsupportedOperationException("Cant close window ${window.name}")
         }
     }
index 6b86c8b5b0458889cd3fc5bd3537f9c239e6bb23..18cd41ddb2d36401321b83acf84364c1c4317afa 100644 (file)
@@ -12,8 +12,8 @@ import ru.deadsoftware.cavedroid.game.input.isInsideHotbar
 import ru.deadsoftware.cavedroid.game.mobs.MobsController
 import ru.deadsoftware.cavedroid.game.mobs.player.Player
 import ru.deadsoftware.cavedroid.game.model.item.Item
-import ru.deadsoftware.cavedroid.game.objects.Drop
-import ru.deadsoftware.cavedroid.game.objects.DropController
+import ru.deadsoftware.cavedroid.game.objects.drop.Drop
+import ru.deadsoftware.cavedroid.game.objects.drop.DropController
 import ru.deadsoftware.cavedroid.misc.Assets
 import javax.inject.Inject
 
index 1b4838a65e63c45ce3d0aa755ea951b1d036fad7..32c7a43f5e221b3b91b4587d4ad3f138481a5415 100644 (file)
@@ -10,7 +10,7 @@ import ru.deadsoftware.cavedroid.game.input.action.keys.MouseInputActionKey
 import ru.deadsoftware.cavedroid.game.input.isInsideWindow
 import ru.deadsoftware.cavedroid.game.mobs.MobsController
 import ru.deadsoftware.cavedroid.game.model.item.InventoryItem
-import ru.deadsoftware.cavedroid.game.objects.DropController
+import ru.deadsoftware.cavedroid.game.objects.drop.DropController
 import ru.deadsoftware.cavedroid.game.ui.windows.GameWindowsConfigs
 import ru.deadsoftware.cavedroid.game.ui.windows.GameWindowsManager
 import ru.deadsoftware.cavedroid.game.ui.windows.inventory.CraftingInventoryWindow
diff --git a/core/src/ru/deadsoftware/cavedroid/game/input/handler/mouse/SelectFurnaceInventoryItemMouseInputHandler.kt b/core/src/ru/deadsoftware/cavedroid/game/input/handler/mouse/SelectFurnaceInventoryItemMouseInputHandler.kt
new file mode 100644 (file)
index 0000000..839135e
--- /dev/null
@@ -0,0 +1,172 @@
+package ru.deadsoftware.cavedroid.game.input.handler.mouse
+
+import com.badlogic.gdx.Gdx
+import com.badlogic.gdx.utils.TimeUtils
+import ru.deadsoftware.cavedroid.game.GameItemsHolder
+import ru.deadsoftware.cavedroid.game.GameScope
+import ru.deadsoftware.cavedroid.game.GameUiWindow
+import ru.deadsoftware.cavedroid.game.input.IGameInputHandler
+import ru.deadsoftware.cavedroid.game.input.action.MouseInputAction
+import ru.deadsoftware.cavedroid.game.input.action.keys.MouseInputActionKey
+import ru.deadsoftware.cavedroid.game.input.isInsideWindow
+import ru.deadsoftware.cavedroid.game.mobs.MobsController
+import ru.deadsoftware.cavedroid.game.model.item.InventoryItem
+import ru.deadsoftware.cavedroid.game.model.item.InventoryItem.Companion.isNoneOrNull
+import ru.deadsoftware.cavedroid.game.objects.drop.DropController
+import ru.deadsoftware.cavedroid.game.objects.furnace.Furnace
+import ru.deadsoftware.cavedroid.game.ui.windows.GameWindowsConfigs
+import ru.deadsoftware.cavedroid.game.ui.windows.GameWindowsManager
+import ru.deadsoftware.cavedroid.game.ui.windows.inventory.FurnaceInventoryWindow
+import ru.deadsoftware.cavedroid.misc.Assets
+import javax.inject.Inject
+
+@GameScope
+class SelectFurnaceInventoryItemMouseInputHandler @Inject constructor(
+    private val gameWindowsManager: GameWindowsManager,
+    private val mobsController: MobsController,
+    private val gameItemsHolder: GameItemsHolder,
+    private val dropController: DropController,
+) : IGameInputHandler<MouseInputAction> {
+
+    private val survivalWindowTexture get() = requireNotNull(Assets.textureRegions["survival"])
+
+    override fun checkConditions(action: MouseInputAction): Boolean {
+        return gameWindowsManager.getCurrentWindow() == GameUiWindow.FURNACE &&
+                isInsideWindow(action, survivalWindowTexture) &&
+                (action.actionKey is MouseInputActionKey.Left || action.actionKey is MouseInputActionKey.Right || action.actionKey is MouseInputActionKey.Screen)
+                && (action.actionKey.touchUp || action.actionKey is MouseInputActionKey.Screen)
+    }
+
+    private fun handleInsideInventoryGrid(action: MouseInputAction, xOnGrid: Int, yOnGrid: Int) {
+        val window = gameWindowsManager.currentWindow as FurnaceInventoryWindow
+
+        var itemIndex = ((xOnGrid.toInt() + yOnGrid.toInt() * GameWindowsConfigs.Furnace.itemsInRow))
+        itemIndex += GameWindowsConfigs.Furnace.hotbarCells
+
+        if (itemIndex >= mobsController.player.inventory.size) {
+            itemIndex -= mobsController.player.inventory.size
+        }
+
+        if (action.actionKey is MouseInputActionKey.Screen) {
+            if (!action.actionKey.touchUp) {
+                window.onLeftCLick(mobsController.player.inventory.items as MutableList<InventoryItem?>, gameItemsHolder, itemIndex, action.actionKey.pointer)
+            } else {
+                if (action.actionKey.pointer == window.selectItemPointer) {
+                    window.onLeftCLick(mobsController.player.inventory.items as MutableList<InventoryItem?>, gameItemsHolder, itemIndex, action.actionKey.pointer)
+                } else {
+                    window.onRightClick(mobsController.player.inventory.items as MutableList<InventoryItem?>, itemIndex)
+                }
+            }
+        } else if (action.actionKey is MouseInputActionKey.Left) {
+            window.onLeftCLick(mobsController.player.inventory.items as MutableList<InventoryItem?>, gameItemsHolder, itemIndex)
+        } else {
+            window.onRightClick(mobsController.player.inventory.items as MutableList<InventoryItem?>, itemIndex)
+        }
+
+        Gdx.app.debug(
+            TAG,
+            "selected item: ${window.selectedItem?.item?.params?.key ?: "null"}; index $itemIndex, grid ($xOnGrid;$yOnGrid)"
+        )
+    }
+
+    private fun handleInsideFuel(action: MouseInputAction) {
+        val window = gameWindowsManager.currentWindow as FurnaceInventoryWindow
+
+        if (!window.selectedItem.isNoneOrNull() && window.selectedItem?.item?.params?.burningTimeMs == null) {
+            return
+        }
+
+        if (action.actionKey is MouseInputActionKey.Screen) {
+            if (!action.actionKey.touchUp) {
+                window.onLeftCLick(window.furnace.items, gameItemsHolder, Furnace.FUEL_INDEX, action.actionKey.pointer)
+            } else {
+                if (action.actionKey.pointer == window.selectItemPointer) {
+                    window.onLeftCLick(window.furnace.items, gameItemsHolder, Furnace.FUEL_INDEX, action.actionKey.pointer)
+                } else {
+                    window.onRightClick(window.furnace.items, Furnace.FUEL_INDEX)
+                }
+            }
+        } else if (action.actionKey is MouseInputActionKey.Left || action.actionKey is MouseInputActionKey.Screen) {
+            window.onLeftCLick(window.furnace.items, gameItemsHolder, Furnace.FUEL_INDEX)
+        } else {
+            window.onRightClick(window.furnace.items, Furnace.FUEL_INDEX)
+        }
+    }
+
+    private fun handleInsideInput(action: MouseInputAction) {
+        val window = gameWindowsManager.currentWindow as FurnaceInventoryWindow
+
+        if (action.actionKey is MouseInputActionKey.Screen) {
+            if (!action.actionKey.touchUp) {
+                window.onLeftCLick(window.furnace.items, gameItemsHolder, Furnace.INPUT_INDEX, action.actionKey.pointer)
+            } else {
+                if (action.actionKey.pointer == window.selectItemPointer) {
+                    window.onLeftCLick(window.furnace.items, gameItemsHolder, Furnace.INPUT_INDEX, action.actionKey.pointer)
+                } else {
+                    window.onRightClick(window.furnace.items, Furnace.INPUT_INDEX)
+                }
+            }
+        } else if (action.actionKey is MouseInputActionKey.Left || action.actionKey is MouseInputActionKey.Screen) {
+            window.onLeftCLick(window.furnace.items, gameItemsHolder, Furnace.INPUT_INDEX)
+        } else {
+            window.onRightClick(window.furnace.items, Furnace.INPUT_INDEX)
+        }
+    }
+
+    override fun handle(action: MouseInputAction) {
+        val survivalTexture = survivalWindowTexture
+        val window = gameWindowsManager.currentWindow as FurnaceInventoryWindow
+
+        val xOnWindow = action.screenX - (action.cameraViewport.width / 2 - survivalTexture.regionWidth / 2)
+        val yOnWindow = action.screenY - (action.cameraViewport.height / 2 - survivalTexture.regionHeight / 2)
+
+        val xOnGrid = (xOnWindow - GameWindowsConfigs.Furnace.itemsGridMarginLeft) /
+                GameWindowsConfigs.Furnace.itemsGridColWidth
+        val yOnGrid = (yOnWindow - GameWindowsConfigs.Furnace.itemsGridMarginTop) /
+                GameWindowsConfigs.Furnace.itemsGridRowHeight
+
+        val isInsideInput = xOnWindow > GameWindowsConfigs.Furnace.smeltInputMarginLeft &&
+                xOnWindow < GameWindowsConfigs.Furnace.smeltInputMarginLeft + GameWindowsConfigs.Furnace.itemsGridColWidth &&
+                yOnWindow > GameWindowsConfigs.Furnace.smeltInputMarginTop &&
+                yOnWindow < GameWindowsConfigs.Furnace.smeltInputMarginTop + GameWindowsConfigs.Furnace.itemsGridRowHeight
+
+        val isInsideFuel = xOnWindow > GameWindowsConfigs.Furnace.smeltFuelMarginLeft &&
+                xOnWindow < GameWindowsConfigs.Furnace.smeltFuelMarginLeft + GameWindowsConfigs.Furnace.itemsGridColWidth &&
+                yOnWindow > GameWindowsConfigs.Furnace.smeltFuelMarginTop &&
+                yOnWindow < GameWindowsConfigs.Furnace.smeltFuelMarginTop + GameWindowsConfigs.Furnace.itemsGridRowHeight
+
+        val isInsideResult = xOnWindow > GameWindowsConfigs.Furnace.smeltResultOffsetX &&
+                xOnWindow < GameWindowsConfigs.Furnace.smeltResultOffsetX + GameWindowsConfigs.Furnace.itemsGridColWidth &&
+                yOnWindow > GameWindowsConfigs.Furnace.smeltResultOffsetY &&
+                yOnWindow < GameWindowsConfigs.Furnace.smeltResultOffsetY + GameWindowsConfigs.Furnace.itemsGridRowHeight
+
+        val isInsideInventoryGrid = xOnGrid >= 0 && xOnGrid < GameWindowsConfigs.Furnace.itemsInRow &&
+                yOnGrid >= 0 && yOnGrid < GameWindowsConfigs.Furnace.itemsInCol
+
+        if (isInsideInventoryGrid) {
+            handleInsideInventoryGrid(action, xOnGrid.toInt(), yOnGrid.toInt())
+        } else if (isInsideFuel) {
+            handleInsideFuel(action)
+        } else if (isInsideInput) {
+            handleInsideInput(action)
+        } else if (isInsideResult && action.actionKey.touchUp) {
+            val selectedItem = window.selectedItem
+            if (selectedItem == null || selectedItem.item.isNone() ||
+                (selectedItem.item == window.furnace.result?.item && selectedItem.amount + (window.furnace.result?.amount ?: 0) <= selectedItem.item.params.maxStack)) {
+
+                if (selectedItem != null && !selectedItem.item.isNone()) {
+                    selectedItem.amount += (window.furnace.result?.amount ?: 0)
+                } else {
+                    window.selectedItem = window.furnace.result
+                }
+                window.furnace.items[Furnace.RESULT_INDEX] = null
+            }
+        }
+
+    }
+
+    companion object {
+        private const val TAG = "SelectFurnaceInventoryItemMouseInputHandler"
+
+    }
+}
\ No newline at end of file
index 91ec3111998f2f7400ffb3576ec4b48843a3d9b0..263d59e90699e9b8874089199c6cc214f5de21f0 100644 (file)
@@ -10,7 +10,7 @@ import ru.deadsoftware.cavedroid.game.input.action.keys.MouseInputActionKey
 import ru.deadsoftware.cavedroid.game.input.isInsideWindow
 import ru.deadsoftware.cavedroid.game.mobs.MobsController
 import ru.deadsoftware.cavedroid.game.model.item.InventoryItem
-import ru.deadsoftware.cavedroid.game.objects.DropController
+import ru.deadsoftware.cavedroid.game.objects.drop.DropController
 import ru.deadsoftware.cavedroid.game.ui.windows.GameWindowsConfigs
 import ru.deadsoftware.cavedroid.game.ui.windows.GameWindowsManager
 import ru.deadsoftware.cavedroid.game.ui.windows.inventory.SurvivalInventoryWindow
index 8ce959222ae36f356cfba860de33213857b52b1b..c5e10d06b30600a2c4aaac74ebedd9a97d67a781 100644 (file)
@@ -3,7 +3,7 @@ package ru.deadsoftware.cavedroid.game.mobs.player
 import ru.deadsoftware.cavedroid.game.GameItemsHolder
 import ru.deadsoftware.cavedroid.game.model.item.InventoryItem
 import ru.deadsoftware.cavedroid.game.model.item.Item
-import ru.deadsoftware.cavedroid.game.objects.Drop
+import ru.deadsoftware.cavedroid.game.objects.drop.Drop
 import ru.deadsoftware.cavedroid.game.ui.TooltipManager
 import java.io.Serializable
 
index 5fcfe319b80f886499cb42f17e53f7d29db5f5db..40b7c7954310345167e8a3ffd5551be232980b48 100644 (file)
@@ -9,8 +9,8 @@ import ru.deadsoftware.cavedroid.game.mobs.Mob;
 import ru.deadsoftware.cavedroid.game.model.block.Block;
 import ru.deadsoftware.cavedroid.game.model.item.InventoryItem;
 import ru.deadsoftware.cavedroid.game.model.item.Item;
-import ru.deadsoftware.cavedroid.game.objects.Drop;
-import ru.deadsoftware.cavedroid.game.objects.DropController;
+import ru.deadsoftware.cavedroid.game.objects.drop.Drop;
+import ru.deadsoftware.cavedroid.game.objects.drop.DropController;
 import ru.deadsoftware.cavedroid.game.ui.TooltipManager;
 import ru.deadsoftware.cavedroid.game.world.GameWorld;
 import ru.deadsoftware.cavedroid.misc.Assets;
index 76c6ac580c0df1a6604c447e3f1c0e930496f456..2e268d046261913cefb1737b0d37bf51703ab198 100644 (file)
@@ -20,14 +20,14 @@ sealed class Block {
     val spriteWidth: Float get() = 16f - params.spriteMargins.left - params.spriteMargins.right
     val spriteHeight: Float get() = 16f - params.spriteMargins.top - params.spriteMargins.bottom
 
-    private var animation: Array<Sprite>? = null
+    protected var animation: Array<Sprite>? = null
 
     private var _sprite: Sprite? = null
         get() {
             return animation?.get(currentAnimationFrame) ?: field
         }
 
-    val sprite: Sprite
+    open val sprite: Sprite
         get() = requireNotNull(_sprite) { "null sprite for block '${params.key}'" }
 
     private val currentAnimationFrame: Int
@@ -111,6 +111,11 @@ sealed class Block {
         return this is Slab
     }
 
+    fun isFurnace(): Boolean {
+        contract { returns(true) implies (this@Block is Furnace) }
+        return this is Furnace
+    }
+
     fun isNone(): Boolean {
         contract { returns(true) implies (this@Block is None) }
         return this is None
@@ -133,6 +138,37 @@ sealed class Block {
         override val params: CommonBlockParams,
     ) : Block()
 
+    data class Furnace(
+        override val params: CommonBlockParams,
+    ): Block() {
+
+        override val sprite: Sprite
+            get() = getSprite(false)
+
+        private fun getSprite(isActive: Boolean): Sprite {
+            return animation?.let { animation ->
+                if (isActive) {
+                    animation[1]
+                } else {
+                    animation[0]
+                }
+            } ?: sprite
+        }
+
+        fun draw(spriter: SpriteBatch, x: Float, y: Float, isActive: Boolean) {
+            getSprite(isActive).apply {
+                setBounds(
+                    /* x = */ x + params.spriteMargins.left,
+                    /* y = */ y + params.spriteMargins.top,
+                    /* width = */ spriteWidth,
+                    /* height = */ spriteHeight
+                )
+                draw(spriter)
+            }
+        }
+
+    }
+
     data class Slab(
         override val params: CommonBlockParams,
         val fullBlockKey: String,
index f3c0544087c53ea3dfd659521f17367a310605a4..373db466baf14f54fb86b352be00acbb8353f3e6 100644 (file)
@@ -17,4 +17,7 @@ data class ItemDto(
     @SerialName("bottom_slab_block") val bottomSlabBlock: String? = null,
     @SerialName("tool_level") val toolLevel: Int? = null,
     @SerialName("max_stack") val maxStack: Int = 64,
+    @SerialName("tint") val tint: String? = null,
+    @SerialName("burning_time") val burningTime: Long? = null,
+    @SerialName("smelt_product") val smeltProduct: String? = null,
 )
index 0330a36f403b3021173179e8b3925becea15511d..00af08b529e17caf6c89ac9051b49a56bd918824 100644 (file)
@@ -7,4 +7,6 @@ data class CommonItemParams(
     val name: String,
     val inHandSpriteOrigin: SpriteOrigin,
     val maxStack: Int,
+    val burningTimeMs: Long?,
+    val smeltProductKey: String?,
 )
\ No newline at end of file
index 765224334d1d29b8441e0f59d1a9b0bd07df503e..acc0d2931efd026c4cfa3dcb9cba8b6e77322ded 100644 (file)
@@ -4,6 +4,7 @@ import com.badlogic.gdx.graphics.Color
 import com.badlogic.gdx.graphics.g2d.SpriteBatch
 import com.badlogic.gdx.graphics.glutils.ShapeRenderer
 import ru.deadsoftware.cavedroid.game.GameItemsHolder
+import ru.deadsoftware.cavedroid.game.mobs.player.Inventory
 import ru.deadsoftware.cavedroid.misc.Assets
 import ru.deadsoftware.cavedroid.misc.utils.drawSprite
 import ru.deadsoftware.cavedroid.misc.utils.drawString
@@ -119,4 +120,7 @@ class InventoryItem @JvmOverloads constructor(
         }
     }
 
+    companion object {
+        fun InventoryItem?.isNoneOrNull() = this?.item == null || this.item.isNone()
+    }
 }
index 1e6755ab7c367b8886301e3173c0664df038e3ec..bf2a55cd6a9d164870c6d4ebb8339310a0bece86 100644 (file)
@@ -46,8 +46,8 @@ sealed class Item {
     }
 
     fun isUsable(): Boolean {
-        contract { returns(true) implies (this@Item is Placeable) }
-        return this is Placeable
+        contract { returns(true) implies (this@Item is Usable) }
+        return this is Usable
     }
 
     @JvmOverloads
@@ -66,10 +66,6 @@ sealed class Item {
         abstract val level: Int
     }
 
-    sealed class Usable : Item() {
-        abstract val useActionKey: String
-    }
-
     sealed class Placeable : Item() {
         abstract val block: BlockModel
         override val sprite: Sprite get() = block.sprite
@@ -82,6 +78,12 @@ sealed class Item {
             get() = throw IllegalAccessException("Trying to get sprite of None")
     }
 
+    data class Usable(
+        override val params: CommonItemParams,
+        override val sprite: Sprite,
+        val useActionKey: String
+    ) : Item()
+
     data class Block(
         override val params: CommonItemParams,
         override val block: BlockModel
@@ -134,11 +136,5 @@ sealed class Item {
         override val blockDamageMultiplier: Float,
         override val level: Int,
     ) : Tool()
-    
-    data class Bucket(
-        override val params: CommonItemParams,
-        override val sprite: Sprite,
-        override val useActionKey: String
-    ) : Usable()
 
 }
\ No newline at end of file
index f45451f6110bd4bac94fd2bdfade5c9678c88374..2ec9727748b3860071fd3738c46603f28caa3a0d 100644 (file)
@@ -23,6 +23,7 @@ class BlockMapper @Inject constructor(
             "water" -> Water(commonBlockParams, requireNotNull(dto.state))
             "lava" -> Lava(commonBlockParams, requireNotNull(dto.state))
             "slab" -> Slab(commonBlockParams, requireNotNull(dto.fullBlock), requireNotNull(dto.otherPart))
+            "furnace" -> Furnace(commonBlockParams)
             "none" -> None(commonBlockParams)
             else -> Normal(commonBlockParams)
         }
index 4557cc82d9a5182e2ca779160bc7c2522d866915..a0949a05d2c082c427cb6ccec26524c6a87a047c 100644 (file)
@@ -11,6 +11,7 @@ import ru.deadsoftware.cavedroid.game.model.item.Item.*
 import ru.deadsoftware.cavedroid.misc.Assets
 import ru.deadsoftware.cavedroid.misc.utils.AssetLoader
 import ru.deadsoftware.cavedroid.misc.utils.SpriteOrigin
+import ru.deadsoftware.cavedroid.misc.utils.colorFromHexString
 import javax.inject.Inject
 
 @Reusable
@@ -23,7 +24,7 @@ class ItemMapper @Inject constructor(
 
         return when (dto.type) {
             "normal" -> Normal(params, requireNotNull(loadSprite(dto)))
-            "bucket" -> Bucket(params, requireNotNull(loadSprite(dto)), requireNotNull(dto.actionKey))
+            "usable" -> Usable(params, requireNotNull(loadSprite(dto)), requireNotNull(dto.actionKey))
             "shovel" -> Shovel(params, requireNotNull(loadSprite(dto)), dto.mobDamageMultiplier, dto.blockDamageMultiplier, requireNotNull(dto.toolLevel))
             "sword" -> Sword(params, requireNotNull(loadSprite(dto)), dto.mobDamageMultiplier, dto.blockDamageMultiplier, requireNotNull(dto.toolLevel))
             "pickaxe" -> Pickaxe(params, requireNotNull(loadSprite(dto)), dto.mobDamageMultiplier, dto.blockDamageMultiplier, requireNotNull(dto.toolLevel))
@@ -45,6 +46,8 @@ class ItemMapper @Inject constructor(
                 y = dto.origin_y,
             ),
             maxStack = dto.maxStack,
+            burningTimeMs = dto.burningTime,
+            smeltProductKey = dto.smeltProduct,
         )
     }
 
@@ -55,7 +58,12 @@ class ItemMapper @Inject constructor(
 
         val texture = Assets.resolveItemTexture(assetLoader, dto.texture)
         return Sprite(texture)
-            .apply { flip(false, true) }
+            .apply {
+                flip(false, true)
+                dto.tint?.let {
+                    color = colorFromHexString(it)
+                }
+            }
     }
 
 }
\ No newline at end of file
similarity index 96%
rename from core/src/ru/deadsoftware/cavedroid/game/objects/Drop.kt
rename to core/src/ru/deadsoftware/cavedroid/game/objects/drop/Drop.kt
index f67c66c742f9526ab7d8f0e557364405062efa09..9099864b39f8c12db0f2362d41a2eecd2739d393 100644 (file)
@@ -1,4 +1,4 @@
-package ru.deadsoftware.cavedroid.game.objects
+package ru.deadsoftware.cavedroid.game.objects.drop
 
 import com.badlogic.gdx.math.Intersector
 import com.badlogic.gdx.math.Rectangle
similarity index 79%
rename from core/src/ru/deadsoftware/cavedroid/game/objects/DropController.java
rename to core/src/ru/deadsoftware/cavedroid/game/objects/drop/DropController.java
index e111f9cf9c0e541380c606ebddbf6daabc4d0ff9..6666fc8f64b7edcc75fddf22ea701403b7ea5b5f 100644 (file)
@@ -1,7 +1,9 @@
-package ru.deadsoftware.cavedroid.game.objects;
+package ru.deadsoftware.cavedroid.game.objects.drop;
 
+import org.jetbrains.annotations.NotNull;
 import ru.deadsoftware.cavedroid.game.GameItemsHolder;
 import ru.deadsoftware.cavedroid.game.GameScope;
+import ru.deadsoftware.cavedroid.game.model.item.InventoryItem;
 import ru.deadsoftware.cavedroid.game.model.item.Item;
 
 import javax.inject.Inject;
@@ -37,6 +39,10 @@ public class DropController implements Serializable {
         mDrops.add(new Drop(x, y, item, count));
     }
 
+    public void addDrop(float x, float y, @NotNull InventoryItem invItem) {
+        addDrop(x, y, invItem.getItem(), invItem.getAmount());
+    }
+
     public int getSize() {
         return mDrops.size();
     }
diff --git a/core/src/ru/deadsoftware/cavedroid/game/objects/furnace/Furnace.kt b/core/src/ru/deadsoftware/cavedroid/game/objects/furnace/Furnace.kt
new file mode 100644 (file)
index 0000000..a6915ef
--- /dev/null
@@ -0,0 +1,147 @@
+package ru.deadsoftware.cavedroid.game.objects.furnace
+
+import com.badlogic.gdx.Gdx
+import com.badlogic.gdx.math.MathUtils
+import com.badlogic.gdx.utils.TimeUtils
+import ru.deadsoftware.cavedroid.game.GameItemsHolder
+import ru.deadsoftware.cavedroid.game.model.item.InventoryItem
+import ru.deadsoftware.cavedroid.game.model.item.InventoryItem.Companion.isNoneOrNull
+import ru.deadsoftware.cavedroid.game.model.item.Item
+import java.io.Serializable
+
+class Furnace : Serializable {
+
+    val items = MutableList<InventoryItem?>(3) { null }
+
+    var fuel: InventoryItem?
+        get() = items[FUEL_INDEX]
+        set(value) {
+            items[FUEL_INDEX] = value
+        }
+
+    var input: InventoryItem?
+        get() = items[INPUT_INDEX]
+        set(value) {
+            items[INPUT_INDEX] = value
+        }
+
+    var result: InventoryItem?
+        get() = items[RESULT_INDEX]
+        set(value) {
+            items[RESULT_INDEX] = value
+        }
+
+    val isActive: Boolean get() = currentFuel != null
+
+    @Transient
+    var currentFuel: Item? = null
+        set(value) {
+            currentFuelKey = value?.params?.key
+            field = value
+        }
+
+    var currentFuelKey: String? = null
+
+    private var startBurnTimeMs = 0L
+    private var smeltStarTimeMs = 0L
+
+    var burnProgress = 0f
+        private set(value) {
+            field = MathUtils.clamp(value, 0f, 1f)
+        }
+    var smeltProgress = 0f
+        private set(value) {
+            field = MathUtils.clamp(value, 0f, 1f)
+        }
+
+    fun init(gameItemsHolder: GameItemsHolder) {
+        currentFuel = currentFuelKey?.let { gameItemsHolder.getItem(it) }
+        items.forEach { it?.init(gameItemsHolder) }
+    }
+
+    fun canSmelt(): Boolean {
+        return (result.isNoneOrNull() || (result?.item?.params?.key == input?.item?.params?.smeltProductKey) )&&
+                !input.isNoneOrNull() && input?.item?.params?.smeltProductKey != null &&
+                (!fuel.isNoneOrNull() || burnProgress > 0f)
+    }
+
+    private fun startBurning() {
+        requireNotNull(fuel?.item?.params?.burningTimeMs) { "Cant start burning without fuel" }
+        currentFuel = fuel!!.item
+        fuel!!.subtract()
+        if (fuel!!.amount <= 0) {
+            fuel = null
+        }
+        startBurnTimeMs = TimeUtils.millis()
+        burnProgress = 0f
+    }
+
+    fun update(gameItemsHolder: GameItemsHolder) {
+        if (currentFuel?.isNone() == true) {
+            currentFuel = null
+        }
+
+        currentFuel?.let { curFuel ->
+            val burningTimeMs = curFuel.params.burningTimeMs ?: run {
+                Gdx.app.error(TAG, "Burning item has no burning time. Item : ${curFuel.params.key}")
+                return
+            }
+
+            if (TimeUtils.timeSinceMillis(startBurnTimeMs).toDouble() / burningTimeMs >= 0.01) {
+                burnProgress += 0.01f
+                startBurnTimeMs = TimeUtils.millis()
+            }
+
+        }
+
+        if (currentFuel != null && burnProgress >= 1f) {
+            if (canSmelt()) {
+                startBurning()
+            } else {
+                currentFuel = null
+                burnProgress = 0f
+                smeltProgress = 0f
+            }
+        }
+
+        if (!canSmelt()) {
+            return
+        }
+        if (currentFuel == null && !fuel.isNoneOrNull()) {
+            startBurning()
+            smeltStarTimeMs = startBurnTimeMs
+            smeltProgress = 0f
+        }
+
+        if ((TimeUtils.timeSinceMillis(smeltStarTimeMs).toDouble() / SMELTING_TIME_MS) >= 0.01) {
+            smeltProgress += 0.01f
+            smeltStarTimeMs = TimeUtils.millis()
+        }
+
+        if (isActive && smeltProgress >= 1f) {
+            val res = gameItemsHolder.getItem(input!!.item.params.smeltProductKey!!)
+            if (result.isNoneOrNull())  {
+                result = res.toInventoryItem()
+            } else {
+                result!!.add()
+            }
+            input!!.subtract()
+            if (input!!.amount <= 0) {
+                input = null
+            }
+            smeltStarTimeMs = TimeUtils.millis()
+            smeltProgress = 0f
+        }
+    }
+
+    companion object {
+        private const val TAG = "Furnace"
+
+        const val FUEL_INDEX = 0
+        const val INPUT_INDEX = 1
+        const val RESULT_INDEX = 2
+
+        const val SMELTING_TIME_MS = 10000L
+    }
+
+}
\ No newline at end of file
diff --git a/core/src/ru/deadsoftware/cavedroid/game/objects/furnace/FurnaceController.kt b/core/src/ru/deadsoftware/cavedroid/game/objects/furnace/FurnaceController.kt
new file mode 100644 (file)
index 0000000..ccc3972
--- /dev/null
@@ -0,0 +1,43 @@
+package ru.deadsoftware.cavedroid.game.objects.furnace
+
+import ru.deadsoftware.cavedroid.game.GameItemsHolder
+import ru.deadsoftware.cavedroid.game.GameScope
+import ru.deadsoftware.cavedroid.game.objects.drop.DropController
+import ru.deadsoftware.cavedroid.misc.utils.px
+import java.io.Serializable
+import javax.inject.Inject
+
+@GameScope
+class FurnaceController @Inject constructor() : Serializable {
+
+    private val furnaceMap = mutableMapOf<String, Furnace>()
+
+    fun init(gameItemsHolder: GameItemsHolder) {
+        furnaceMap.forEach { _, fur -> fur.init(gameItemsHolder) }
+    }
+
+    fun getFurnace(x: Int, y: Int, z: Int): Furnace? {
+        return furnaceMap["$x;$y;$z"]
+    }
+
+    fun addFurnace(x: Int, y: Int, z: Int) {
+        furnaceMap["$x;$y;$z"] = Furnace()
+    }
+
+    fun destroyFurnace(x: Int, y: Int, z: Int, dropController: DropController) {
+        val furnace = furnaceMap.remove("$x;$y;$z") ?: return
+        val xPx = (x + .5f).px
+        val yPx = (y + .5f).px
+
+        furnace.input?.let { dropController.addDrop(xPx, yPx, it) }
+        furnace.fuel?.let { dropController.addDrop(xPx, yPx, it) }
+        furnace.result?.let { dropController.addDrop(xPx, yPx, it) }
+    }
+
+    fun update(gameItemsHolder: GameItemsHolder) {
+        furnaceMap.forEach { _, furnace ->
+            furnace.update(gameItemsHolder)
+        }
+    }
+
+}
\ No newline at end of file
index 378ed7b9191c048884db9d80fdc953e7273cb155..5af20e82f86a6b02ed319457fa97581c8edd425f 100644 (file)
@@ -2,7 +2,6 @@ package ru.deadsoftware.cavedroid.game.render
 
 import com.badlogic.gdx.graphics.g2d.Sprite
 import com.badlogic.gdx.graphics.g2d.SpriteBatch
-import com.badlogic.gdx.graphics.g2d.TextureRegion
 import com.badlogic.gdx.graphics.glutils.ShapeRenderer
 import com.badlogic.gdx.math.MathUtils
 import com.badlogic.gdx.math.Rectangle
@@ -87,7 +86,11 @@ abstract class BlocksRenderer(
         if (foregroundBlock.canSeeThrough && !backgroundBlock.isNone()) {
             val drawX = x.px - viewport.x
             val drawY = y.px - viewport.y
-            backgroundBlock.draw(spriteBatch, drawX, drawY)
+            if (backgroundBlock.isFurnace()) {
+                backgroundBlock.draw(spriteBatch, drawX, drawY, gameWorld.getBackgroundFurnace(x, y)?.isActive ?: false)
+            } else {
+                backgroundBlock.draw(spriteBatch, drawX, drawY)
+            }
         }
     }
 
@@ -97,7 +100,12 @@ abstract class BlocksRenderer(
         if (!foregroundBlock.isNone() && foregroundBlock.params.isBackground == background) {
             val drawX = x.px - viewport.x
             val drawY = y.px - viewport.y
-            foregroundBlock.draw(spriteBatch, drawX, drawY)
+
+            if (foregroundBlock.isFurnace()) {
+                foregroundBlock.draw(spriteBatch, drawX, drawY, gameWorld.getForegroundFurnace(x, y)?.isActive ?: false)
+            } else {
+                foregroundBlock.draw(spriteBatch, drawX, drawY)
+            }
         }
     }
 
index a17bd613002ddb1922151bb6d3df31b92f92c969..f14d36b943a7389d546824d48f7e786d320fe4fc 100644 (file)
@@ -4,7 +4,7 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch
 import com.badlogic.gdx.graphics.glutils.ShapeRenderer
 import com.badlogic.gdx.math.Rectangle
 import ru.deadsoftware.cavedroid.game.GameScope
-import ru.deadsoftware.cavedroid.game.objects.DropController
+import ru.deadsoftware.cavedroid.game.objects.drop.DropController
 import ru.deadsoftware.cavedroid.game.world.GameWorld
 import ru.deadsoftware.cavedroid.misc.utils.cycledInsideWorld
 import ru.deadsoftware.cavedroid.misc.utils.drawSprite
index 03df48f4178e307a159b2c83944abfd3e07b678c..f87c5bda2bbb165eef14154a0d143edfa8417687 100644 (file)
@@ -8,6 +8,7 @@ import ru.deadsoftware.cavedroid.game.GameScope
 import ru.deadsoftware.cavedroid.game.GameUiWindow
 import ru.deadsoftware.cavedroid.game.render.windows.CraftingWindowRenderer
 import ru.deadsoftware.cavedroid.game.render.windows.CreativeWindowRenderer
+import ru.deadsoftware.cavedroid.game.render.windows.FurnaceWindowRenderer
 import ru.deadsoftware.cavedroid.game.render.windows.SurvivalWindowRenderer
 import ru.deadsoftware.cavedroid.game.ui.windows.GameWindowsManager
 import javax.inject.Inject
@@ -18,6 +19,7 @@ class WindowsRenderer @Inject constructor(
     private val survivalWindowRenderer: SurvivalWindowRenderer,
     private val craftingWindowRenderer: CraftingWindowRenderer,
     private val gameWindowsManager: GameWindowsManager,
+    private val furnaceWindowRenderer: FurnaceWindowRenderer,
 ) : IGameRenderer {
 
     override val renderLayer get() = RENDER_LAYER
@@ -27,6 +29,7 @@ class WindowsRenderer @Inject constructor(
             GameUiWindow.CREATIVE_INVENTORY -> creativeWindowRenderer.draw(spriteBatch, shapeRenderer, viewport, delta)
             GameUiWindow.SURVIVAL_INVENTORY -> survivalWindowRenderer.draw(spriteBatch, shapeRenderer, viewport, delta)
             GameUiWindow.CRAFTING_TABLE -> craftingWindowRenderer.draw(spriteBatch, shapeRenderer, viewport, delta)
+            GameUiWindow.FURNACE -> furnaceWindowRenderer.draw(spriteBatch, shapeRenderer, viewport, delta)
             GameUiWindow.NONE -> return
             else -> Gdx.app.error(TAG, "Cannot draw window: ${windowType.name}")
         }
diff --git a/core/src/ru/deadsoftware/cavedroid/game/render/windows/FurnaceWindowRenderer.kt b/core/src/ru/deadsoftware/cavedroid/game/render/windows/FurnaceWindowRenderer.kt
new file mode 100644 (file)
index 0000000..a963502
--- /dev/null
@@ -0,0 +1,139 @@
+package ru.deadsoftware.cavedroid.game.render.windows
+
+import com.badlogic.gdx.Gdx
+import com.badlogic.gdx.graphics.g2d.SpriteBatch
+import com.badlogic.gdx.graphics.glutils.ShapeRenderer
+import com.badlogic.gdx.math.Rectangle
+import com.badlogic.gdx.utils.TimeUtils
+import ru.deadsoftware.cavedroid.MainConfig
+import ru.deadsoftware.cavedroid.game.GameItemsHolder
+import ru.deadsoftware.cavedroid.game.GameScope
+import ru.deadsoftware.cavedroid.game.mobs.MobsController
+import ru.deadsoftware.cavedroid.game.objects.furnace.Furnace
+import ru.deadsoftware.cavedroid.game.render.IGameRenderer
+import ru.deadsoftware.cavedroid.game.render.WindowsRenderer
+import ru.deadsoftware.cavedroid.game.ui.windows.GameWindowsConfigs
+import ru.deadsoftware.cavedroid.game.ui.windows.GameWindowsManager
+import ru.deadsoftware.cavedroid.game.ui.windows.inventory.FurnaceInventoryWindow
+import ru.deadsoftware.cavedroid.misc.Assets
+import ru.deadsoftware.cavedroid.misc.utils.drawSprite
+import ru.deadsoftware.cavedroid.misc.utils.withScissors
+import javax.inject.Inject
+
+@GameScope
+class FurnaceWindowRenderer @Inject constructor(
+    private val mainConfig: MainConfig,
+    private val mobsController: MobsController,
+    private val gameWindowsManager: GameWindowsManager,
+    private val gameItemsHolder: GameItemsHolder,
+) : AbstractWindowRenderer(), IGameRenderer {
+
+    override val renderLayer get() = WindowsRenderer.RENDER_LAYER
+
+    private val furnaceWindowTexture get() = requireNotNull(Assets.textureRegions[FURNACE_WINDOW_KEY])
+
+    
+    override fun draw(spriteBatch: SpriteBatch, shapeRenderer: ShapeRenderer, viewport: Rectangle, delta: Float) {
+        val windowTexture = furnaceWindowTexture
+        
+        val window = gameWindowsManager.currentWindow as FurnaceInventoryWindow
+
+        val windowX = viewport.width / 2 - windowTexture.regionWidth / 2
+        val windowY = viewport.height / 2 - windowTexture.regionHeight / 2
+
+        spriteBatch.draw(windowTexture, windowX, windowY)
+        drawItemsGrid(
+            spriteBatch = spriteBatch,
+            shapeRenderer = shapeRenderer,
+            gridX = windowX + GameWindowsConfigs.Furnace.itemsGridMarginLeft,
+            gridY = windowY + GameWindowsConfigs.Furnace.itemsGridMarginTop,
+            items = mobsController.player.inventory.items.asSequence()
+                .drop(GameWindowsConfigs.Furnace.hotbarCells)
+                .take(GameWindowsConfigs.Furnace.itemsInCol * GameWindowsConfigs.Furnace.itemsInRow)
+                .asIterable(),
+            itemsInRow = GameWindowsConfigs.Furnace.itemsInRow,
+            cellWidth = GameWindowsConfigs.Furnace.itemsGridColWidth,
+            cellHeight = GameWindowsConfigs.Furnace.itemsGridRowHeight,
+        )
+
+        drawItemsGrid(
+            spriteBatch = spriteBatch,
+            shapeRenderer = shapeRenderer,
+            gridX = windowX + GameWindowsConfigs.Furnace.itemsGridMarginLeft,
+            gridY = windowY + windowTexture.regionHeight - GameWindowsConfigs.Furnace.hotbarOffsetFromBottom,
+            items = mobsController.player.inventory.items.asSequence()
+                .take(GameWindowsConfigs.Furnace.hotbarCells)
+                .asIterable(),
+            itemsInRow = GameWindowsConfigs.Furnace.hotbarCells,
+            cellWidth = GameWindowsConfigs.Furnace.itemsGridColWidth,
+            cellHeight = GameWindowsConfigs.Furnace.itemsGridRowHeight,
+        )
+
+        window.furnace.fuel?.draw(
+            spriteBatch = spriteBatch,
+            shapeRenderer = shapeRenderer,
+            x = windowX + GameWindowsConfigs.Furnace.smeltFuelMarginLeft,
+            y = windowY + GameWindowsConfigs.Furnace.smeltFuelMarginTop
+        )
+
+        window.furnace.input?.draw(
+            spriteBatch = spriteBatch,
+            shapeRenderer = shapeRenderer,
+            x = windowX + GameWindowsConfigs.Furnace.smeltInputMarginLeft,
+            y = windowY + GameWindowsConfigs.Furnace.smeltInputMarginTop
+        )
+
+        window.furnace.result?.draw(
+            spriteBatch = spriteBatch,
+            shapeRenderer = shapeRenderer,
+            x = windowX + GameWindowsConfigs.Furnace.smeltResultOffsetX,
+            y = windowY + GameWindowsConfigs.Furnace.smeltResultOffsetY
+        )
+
+        if (window.furnace.isActive) {
+            val burn = GameWindowsConfigs.Furnace.fuelBurnHeight * window.furnace.burnProgress
+
+            spriteBatch.withScissors(
+                mainConfig = mainConfig,
+                x = windowX + GameWindowsConfigs.Furnace.fuelBurnMarginLeft,
+                y = windowY + GameWindowsConfigs.Furnace.fuelBurnMarginTop + burn,
+                width = Assets.furnaceBurn.width,
+                height = GameWindowsConfigs.Furnace.fuelBurnHeight,
+            ) {
+                spriteBatch.drawSprite(
+                    sprite = Assets.furnaceBurn,
+                    x = windowX + GameWindowsConfigs.Furnace.fuelBurnMarginLeft,
+                    y = windowY + GameWindowsConfigs.Furnace.fuelBurnMarginTop
+                )
+            }
+
+            if (window.furnace.canSmelt()) {
+                val progress = GameWindowsConfigs.Furnace.progressWidth * window.furnace.smeltProgress
+
+                spriteBatch.withScissors(
+                    mainConfig = mainConfig,
+                    x = windowX + GameWindowsConfigs.Furnace.progressMarginLeft,
+                    y = windowY + GameWindowsConfigs.Furnace.progressMarginTop,
+                    width = progress,
+                    height = Assets.furnaceProgress.height
+                ) {
+                    spriteBatch.drawSprite(
+                        sprite = Assets.furnaceProgress,
+                        x = windowX + GameWindowsConfigs.Furnace.progressMarginLeft,
+                        y = windowY + GameWindowsConfigs.Furnace.progressMarginTop,
+                    )
+                }
+            }
+        }
+
+        window.selectedItem?.drawSelected(
+            spriteBatch = spriteBatch,
+            x = Gdx.input.x * (viewport.width / Gdx.graphics.width),
+            y = Gdx.input.y * (viewport.height / Gdx.graphics.height)
+        )
+    }
+
+    companion object {
+        private const val FURNACE_WINDOW_KEY = "furnace"
+    }
+}
\ No newline at end of file
index 8fa3fb2a7a1f216ba8a255b74395d176feef0365..faef9939cf0e21c83586b09278786f339b74b793 100644 (file)
@@ -70,4 +70,35 @@ object GameWindowsConfigs {
         const val craftResultOffsetX = 128f
         const val craftResultOffsetY = 36f
     }
+
+    data object Furnace {
+        const val itemsGridMarginLeft = 8f
+        const val itemsGridMarginTop = 84f
+
+        const val itemsGridRowHeight = 18f
+        const val itemsGridColWidth = 18f
+
+        const val itemsInRow = 9
+        const val itemsInCol = 5
+
+        const val hotbarOffsetFromBottom = 24f
+        const val hotbarCells = 9
+
+        const val smeltInputMarginLeft = 56f
+        const val smeltInputMarginTop = 18f
+
+        const val smeltFuelMarginLeft = 56f
+        const val smeltFuelMarginTop = 54f
+
+        const val smeltResultOffsetX = 128f
+        const val smeltResultOffsetY = 36f
+
+        const val fuelBurnMarginLeft = 56f
+        const val fuelBurnMarginTop = 36f
+        const val fuelBurnHeight = 14f
+
+        const val progressMarginLeft = 79f
+        const val progressMarginTop = 34f
+        const val progressWidth = 24f
+    }
 }
\ No newline at end of file
index 05c8a9b25b24dcb72a1d985869e9fd63b4285189..1b6611af1e06601615ebc4d6802801c6491cee86 100644 (file)
@@ -3,12 +3,10 @@ package ru.deadsoftware.cavedroid.game.ui.windows
 import ru.deadsoftware.cavedroid.game.GameScope
 import ru.deadsoftware.cavedroid.game.GameUiWindow
 import ru.deadsoftware.cavedroid.game.mobs.MobsController
-import ru.deadsoftware.cavedroid.game.objects.DropController
+import ru.deadsoftware.cavedroid.game.objects.drop.DropController
+import ru.deadsoftware.cavedroid.game.objects.furnace.Furnace
 import ru.deadsoftware.cavedroid.game.ui.TooltipManager
-import ru.deadsoftware.cavedroid.game.ui.windows.inventory.AbstractInventoryWindow
-import ru.deadsoftware.cavedroid.game.ui.windows.inventory.CraftingInventoryWindow
-import ru.deadsoftware.cavedroid.game.ui.windows.inventory.CreativeInventoryWindow
-import ru.deadsoftware.cavedroid.game.ui.windows.inventory.SurvivalInventoryWindow
+import ru.deadsoftware.cavedroid.game.ui.windows.inventory.*
 import javax.inject.Inject
 
 @GameScope
@@ -36,6 +34,10 @@ class GameWindowsManager @Inject constructor(
         }
     }
 
+    fun openFurnace(furnace: Furnace) {
+        currentWindow = FurnaceInventoryWindow(furnace)
+    }
+
     fun openCrafting() {
         currentWindow = CraftingInventoryWindow()
     }
diff --git a/core/src/ru/deadsoftware/cavedroid/game/ui/windows/inventory/FurnaceInventoryWindow.kt b/core/src/ru/deadsoftware/cavedroid/game/ui/windows/inventory/FurnaceInventoryWindow.kt
new file mode 100644 (file)
index 0000000..5adaac6
--- /dev/null
@@ -0,0 +1,15 @@
+package ru.deadsoftware.cavedroid.game.ui.windows.inventory
+
+import ru.deadsoftware.cavedroid.game.GameUiWindow
+import ru.deadsoftware.cavedroid.game.model.item.InventoryItem
+import ru.deadsoftware.cavedroid.game.objects.furnace.Furnace
+
+class FurnaceInventoryWindow(
+    val furnace: Furnace,
+) : AbstractInventoryWindow() {
+
+    override val type = GameUiWindow.FURNACE
+
+    override var selectedItem: InventoryItem? = null
+
+}
\ No newline at end of file
index 686f1c946c81f55fb90ef5d4578538a6d85e3c2f..0d5a80ae49cf7fccbf9d7c3aff5723e451bf5c84 100644 (file)
@@ -8,7 +8,9 @@ import ru.deadsoftware.cavedroid.game.model.block.Block;
 import ru.deadsoftware.cavedroid.game.model.item.InventoryItem;
 import ru.deadsoftware.cavedroid.game.model.item.Item;
 import ru.deadsoftware.cavedroid.game.model.world.generator.WorldGeneratorConfig;
-import ru.deadsoftware.cavedroid.game.objects.DropController;
+import ru.deadsoftware.cavedroid.game.objects.drop.DropController;
+import ru.deadsoftware.cavedroid.game.objects.furnace.Furnace;
+import ru.deadsoftware.cavedroid.game.objects.furnace.FurnaceController;
 import ru.deadsoftware.cavedroid.misc.utils.MeasureUnitsUtilsKt;
 
 import javax.annotation.CheckForNull;
@@ -20,6 +22,7 @@ public class GameWorld {
     private final DropController mDropController;
     private final MobsController mMobsController;
     private final GameItemsHolder mGameItemsHolder;
+    private final FurnaceController mFurnaceController;
 
     private final int mWidth;
     private final int mHeight;
@@ -32,11 +35,13 @@ public class GameWorld {
     public GameWorld(DropController dropController,
                      MobsController mobsController,
                      GameItemsHolder gameItemsHolder,
+                     FurnaceController furnaceController,
                      @CheckForNull Block[][] foreMap,
                      @CheckForNull Block[][] backMap) {
         mDropController = dropController;
         mMobsController = mobsController;
         mGameItemsHolder = gameItemsHolder;
+        mFurnaceController = furnaceController;
 
         boolean isNewGame = foreMap == null || backMap == null;
 
@@ -170,6 +175,11 @@ public class GameWorld {
 
     public boolean placeToForeground(int x, int y, Block value) {
         if (!hasForeAt(x, y) || value == mGameItemsHolder.getFallbackBlock() || !getForeMap(x, y).hasCollision()) {
+
+            if (value.isFurnace()) {
+                mFurnaceController.addFurnace(x, y, 0);
+            }
+
             setForeMap(x, y, value);
             return true;
         } else if (value instanceof Block.Slab && isSameSlab(value, getForeMap(x, y))) {
@@ -182,6 +192,9 @@ public class GameWorld {
     public boolean placeToBackground(int x, int y, Block value) {
         if (value == mGameItemsHolder.getFallbackBlock() || (getBackMap(x, y) == mGameItemsHolder.getFallbackBlock() && value.hasCollision()) &&
                 (!value.isTransparent() || value == mGameItemsHolder.getBlock("glass"))) {
+            if (value.isFurnace()) {
+                mFurnaceController.addFurnace(x, y, 1);
+            }
             setBackMap(x, y, value);
             return true;
         }
@@ -206,6 +219,9 @@ public class GameWorld {
 
     public void destroyForeMap(int x, int y) {
         Block block = getForeMap(x, y);
+        if (block.isFurnace()) {
+            mFurnaceController.destroyFurnace(x, y, 0, mDropController);
+        }
         if (block.hasDrop() && shouldDrop(block)) {
             for (int i = 0; i < block.getParams().getDropInfo().getCount(); i++) {
                 mDropController.addDrop(transformX(x) * 16 + 4, y * 16 + 4, mGameItemsHolder.getItem(block.getDrop()));
@@ -221,6 +237,9 @@ public class GameWorld {
 
     public void destroyBackMap(int x, int y) {
         Block block = getBackMap(x, y);
+        if (block.isFurnace()) {
+            mFurnaceController.destroyFurnace(x, y, 0, mDropController);
+        }
         if (block.hasDrop() && shouldDrop(block)) {
             for (int i = 0; i < block.getParams().getDropInfo().getCount(); i++) {
                 mDropController.addDrop(transformX(x) * 16 + 4, y * 16 + 4, mGameItemsHolder.getItem(block.getDrop()));
@@ -229,4 +248,14 @@ public class GameWorld {
         playerDurateTool();
         placeToBackground(x, y, mGameItemsHolder.getFallbackBlock());
     }
+
+    @CheckForNull
+    public Furnace getForegroundFurnace(int x, int y) {
+        return mFurnaceController.getFurnace(x, y, 0);
+    }
+
+    @CheckForNull
+    public Furnace getBackgroundFurnace(int x, int y) {
+        return mFurnaceController.getFurnace(x, y, 1);
+    }
 }
\ No newline at end of file
index 329207f677299a79d8430eb68e1aab9bc63a0a1c..ffc253f1df71e831864fd784fd3244c2062faddb 100644 (file)
@@ -44,6 +44,9 @@ public class Assets {
     public static Sprite joyBackground;
     public static Sprite joyStick;
 
+    public static Sprite furnaceBurn;
+    public static Sprite furnaceProgress;
+
     public static void dispose() {
         minecraftFont.dispose();
         loadedTextures.forEach(Texture::dispose);
@@ -196,6 +199,11 @@ public class Assets {
         joyBackground = new Sprite(loadTexture(assetLoader.getAssetHandle("joy_background.png")));
     }
 
+    private static void loadFurnace(AssetLoader assetLoader) {
+        furnaceBurn = new Sprite(textureRegions.get("furnace_burn"));
+        furnaceProgress = new Sprite(textureRegions.get("furnace_progress"));
+    }
+
     public static void load(final AssetLoader assetLoader) {
         loadMob(assetLoader, playerSprite, "char");
         loadMob(assetLoader, pigSprite, "pig");
@@ -205,6 +213,7 @@ public class Assets {
         loadItems(assetLoader);
         loadTouchButtonsFromJSON(assetLoader);
         loadJoystick(assetLoader);
+        loadFurnace(assetLoader);
         setPlayerHeadOrigin();
         minecraftFont = new BitmapFont(assetLoader.getAssetHandle("font.fnt"), true);
         minecraftFont.getData().setScale(.375f);
index ecf1ce03298afa5cbb7a24f05a79d30e3d4b2db8..24103e7009601080eecffde9de2d6eeebff7f72f 100644 (file)
@@ -15,4 +15,4 @@ val Int.px get() = this * 16f
 /**
  * Converts this value in PIXELS into blocks
  */
-val Float.bl get() = MathUtils.floor(this / 16)
\ No newline at end of file
+val Float.bl get() = MathUtils.floor(this / 16f)
\ No newline at end of file
index 8976c9963cd8935d64a373ee54db088513537662..917f69b591933ee9a6bfc83354e5f012c0894363 100644 (file)
@@ -1,9 +1,12 @@
 package ru.deadsoftware.cavedroid.misc.utils
 
+import com.badlogic.gdx.Gdx
 import com.badlogic.gdx.graphics.Color
+import com.badlogic.gdx.graphics.GL20
 import com.badlogic.gdx.graphics.g2d.GlyphLayout
 import com.badlogic.gdx.graphics.g2d.SpriteBatch
 import com.badlogic.gdx.math.Rectangle
+import ru.deadsoftware.cavedroid.MainConfig
 import ru.deadsoftware.cavedroid.misc.Assets
 
 private fun Rectangle.shifted(shift: Float) = Rectangle(x + shift, y, width, height)
@@ -69,3 +72,27 @@ fun colorFromHexString(hex: String): Color {
     rgba = (rgba shl 8) or 0xFF
     return Color(rgba)
 }
+
+fun SpriteBatch.withScissors(
+    mainConfig: MainConfig,
+    x: Float,
+    y: Float,
+    width: Float,
+    height: Float,
+    block: () -> Unit
+) {
+    val scaleX = Gdx.graphics.width / mainConfig.width
+    val scaleY = Gdx.graphics.height / mainConfig.height
+
+    flush()
+    Gdx.gl.glEnable(GL20.GL_SCISSOR_TEST)
+    Gdx.gl.glScissor(
+        /* x = */ (x * scaleX).toInt(),
+        /* y = */ ((mainConfig.height - y - height) * scaleY).toInt(),
+        /* width = */ (width * scaleX).toInt(),
+        /* height = */ (height * scaleY).toInt()
+    )
+    block.invoke()
+    flush()
+    Gdx.gl.glDisable(GL20.GL_SCISSOR_TEST)
+}