From: fredboy Date: Sat, 20 Apr 2024 15:29:45 +0000 (+0700) Subject: Store block references intead of ids X-Git-Tag: alpha0.6.0~17 X-Git-Url: https://deadsoftware.ru/gitweb?p=cavedroid.git;a=commitdiff_plain;h=1c004c0ce7e183e773b5b486295c25e39732e899 Store block references intead of ids --- diff --git a/android/assets/json/game_items.json b/android/assets/json/game_items.json index cd2fae9..279e13f 100644 --- a/android/assets/json/game_items.json +++ b/android/assets/json/game_items.json @@ -123,7 +123,7 @@ "lava": { "animated": true, "collision": false, - "fluid": true, + "state": 0, "frames": 16, "hp": -1, "id": 9, @@ -133,7 +133,7 @@ "lava_12": { "animated": true, "collision": false, - "fluid": true, + "state": 2, "frames": 16, "hp": -1, "id": 65, @@ -145,7 +145,7 @@ "lava_16": { "animated": true, "collision": false, - "fluid": true, + "state": 1, "frames": 16, "hp": -1, "id": 64, @@ -155,7 +155,7 @@ "lava_4": { "animated": true, "collision": false, - "fluid": true, + "state": 4, "frames": 16, "hp": -1, "id": 67, @@ -167,7 +167,7 @@ "lava_8": { "animated": true, "collision": false, - "fluid": true, + "state": 3, "frames": 16, "hp": -1, "id": 66, @@ -295,7 +295,7 @@ "water": { "animated": true, "collision": false, - "fluid": true, + "state": 0, "frames": 16, "hp": -1, "id": 8, @@ -306,7 +306,7 @@ "water_12": { "animated": true, "collision": false, - "fluid": true, + "state": 2, "frames": 16, "hp": -1, "id": 61, @@ -319,7 +319,7 @@ "water_16": { "animated": true, "collision": false, - "fluid": true, + "state": 1, "frames": 16, "hp": -1, "id": 60, @@ -330,7 +330,7 @@ "water_4": { "animated": true, "collision": false, - "fluid": true, + "state": 4, "frames": 16, "hp": -1, "id": 63, @@ -343,7 +343,7 @@ "water_8": { "animated": true, "collision": false, - "fluid": true, + "state": 3, "frames": 16, "hp": -1, "id": 62, diff --git a/core/src/ru/deadsoftware/cavedroid/game/GameInput.java b/core/src/ru/deadsoftware/cavedroid/game/GameInput.java index bab16fd..3282652 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/GameInput.java +++ b/core/src/ru/deadsoftware/cavedroid/game/GameInput.java @@ -21,7 +21,6 @@ import ru.deadsoftware.cavedroid.game.world.GameWorld; import ru.deadsoftware.cavedroid.misc.Assets; import ru.deadsoftware.cavedroid.misc.ControlMode; -import javax.annotation.CheckForNull; import javax.inject.Inject; import java.util.Map; @@ -37,6 +36,7 @@ public class GameInput { private final GameWorld mGameWorld; private final DropController mDropController; private final MobsController mMobsController; + private final GameItemsHolder mGameItemsHolder; private final Map mUseItemActionMap; private final Map mPlaceBlockActionMap; @@ -64,12 +64,14 @@ public class GameInput { GameWorld gameWorld, DropController dropController, MobsController mobsController, + GameItemsHolder gameItemsHolder, Map useItemActionMap, Map placeBlockActionMap) { mMainConfig = mainConfig; mGameWorld = gameWorld; mDropController = dropController; mMobsController = mobsController; + mGameItemsHolder = gameItemsHolder; mUseItemActionMap = useItemActionMap; mPlaceBlockActionMap = placeBlockActionMap; @@ -79,7 +81,7 @@ public class GameInput { } private boolean checkSwim() { - return GameItems.isFluid(mGameWorld.getForeMap(mPlayer.getMapX(), mPlayer.getLowerMapY())); + return mGameWorld.getForeMap(mPlayer.getMapX(), mPlayer.getLowerMapY()).isFluid(); } private void goUpwards() { @@ -150,7 +152,7 @@ public class GameInput { } private boolean isNotAutoselectable(int x, int y) { - return (!mGameWorld.hasForeAt(x, y) || !mGameWorld.getForeMapBlock(x, y).hasCollision()); + return (!mGameWorld.hasForeAt(x, y) || !mGameWorld.getForeMap(x, y).hasCollision()); } private void checkCursorBounds() { @@ -247,27 +249,27 @@ public class GameInput { if (mMainConfig.checkGameUiWindow(GameUiWindow.NONE)) { mPlayer.startHitting(); - if ((mGameWorld.hasForeAt(mCurX, mCurY) && mGameWorld.getForeMapBlock(mCurX, mCurY).getHp() >= 0) || + if ((mGameWorld.hasForeAt(mCurX, mCurY) && mGameWorld.getForeMap(mCurX, mCurY).getHp() >= 0) || (!mGameWorld.hasForeAt(mCurX, mCurY) && mGameWorld.hasBackAt(mCurX, mCurY) && - mGameWorld.getBackMapBlock(mCurX, mCurY).getHp() >= 0)) { + mGameWorld.getBackMap(mCurX, mCurY).getHp() >= 0)) { if (mPlayer.gameMode == 0) { mBlockDamage++; if (mGameWorld.hasForeAt(mCurX, mCurY)) { - if (mBlockDamage >= mGameWorld.getForeMapBlock(mCurX, mCurY).getHp()) { + if (mBlockDamage >= mGameWorld.getForeMap(mCurX, mCurY).getHp()) { mGameWorld.destroyForeMap(mCurX, mCurY); mBlockDamage = 0; } } else if (mGameWorld.hasBackAt(mCurX, mCurY)) { - if (mBlockDamage >= mGameWorld.getBackMapBlock(mCurX, mCurY).getHp()) { + if (mBlockDamage >= mGameWorld.getBackMap(mCurX, mCurY).getHp()) { mGameWorld.destroyBackMap(mCurX, mCurY); mBlockDamage = 0; } } } else { if (mGameWorld.hasForeAt(mCurX, mCurY)) { - mGameWorld.placeToForeground(mCurX, mCurY, 0); + mGameWorld.placeToForeground(mCurX, mCurY, mGameItemsHolder.getFallbackBlock()); } else if (mGameWorld.hasBackAt(mCurX, mCurY)) { - mGameWorld.placeToBackground(mCurX, mCurY, 0); + mGameWorld.placeToBackground(mCurX, mCurY, mGameItemsHolder.getFallbackBlock()); } mTouchedDown = false; } @@ -336,10 +338,6 @@ public class GameInput { pig.attachToController(mMobsController); break; - case Input.Keys.Q: - mGameWorld.placeToForeground(mCurX, mCurY, 8); - break; - case Input.Keys.GRAVE: mMobsController.getPlayer().gameMode = (mMobsController.getPlayer().gameMode + 1) % 2; break; diff --git a/core/src/ru/deadsoftware/cavedroid/game/GameItems.java b/core/src/ru/deadsoftware/cavedroid/game/GameItems.java index 4024c36..370f1b0 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/GameItems.java +++ b/core/src/ru/deadsoftware/cavedroid/game/GameItems.java @@ -55,12 +55,6 @@ public class GameItems { return getBlock(id) instanceof Block.Slab; } - public static boolean fluidCanFlowThere(int thisId, int thatId) { - return thatId == 0 || (!getBlock(thatId).hasCollision() && !isFluid(thatId)) || - (isWater(thisId) && isWater(thatId) && thisId < thatId) || - (isLava(thisId) && isLava(thatId) && thisId < thatId); - } - public static Block getBlock(int id) { return blocks.getValueAt(id); } @@ -148,6 +142,7 @@ public class GameItems { int id = Assets.getIntFromJson(block, "id", count); int dropCount = Assets.getIntFromJson(block, "drop_count", 1); String fullBlock = Assets.getStringFromJson(block, "full_block", null); + int state = Assets.getIntFromJson(block, "state", 0); blocksIds.put(key, id); if (count >= id) { @@ -178,8 +173,8 @@ public class GameItems { ); Block newBlock = switch (meta) { - case "water" -> new Block.Water(params); - case "lava" -> new Block.Lava(params); + case "water" -> new Block.Water(params, state); + case "lava" -> new Block.Lava(params, state); case "slab" -> new Block.Slab(params, fullBlock); default -> new Block.Normal(params); }; diff --git a/core/src/ru/deadsoftware/cavedroid/game/GameItemsHolder.kt b/core/src/ru/deadsoftware/cavedroid/game/GameItemsHolder.kt index 73da0c2..058e84d 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/GameItemsHolder.kt +++ b/core/src/ru/deadsoftware/cavedroid/game/GameItemsHolder.kt @@ -14,6 +14,7 @@ import javax.inject.Inject @GameScope class GameItemsHolder @Inject constructor( + private val assetLoader: AssetLoader, private val blockMapper: BlockMapper, private val itemMapper: ItemMapper, ) { @@ -23,14 +24,19 @@ class GameItemsHolder @Inject constructor( private val blocksMap = LinkedHashMap() private val itemsMap = LinkedHashMap() - private lateinit var fallbackBlock: Block - private lateinit var fallbackItem: Item - + lateinit var fallbackBlock: Block + private set + lateinit var fallbackItem: Item + private set + init { + initialize() + } private fun loadBlocks(dtoMap: Map) { dtoMap.forEach { (key, dto) -> blocksMap[key] = blockMapper.map(key, dto) + .apply(Block::initialize) } fallbackBlock = blocksMap[FALLBACK_BLOCK_KEY] @@ -50,7 +56,7 @@ class GameItemsHolder @Inject constructor( ?: throw IllegalArgumentException("Fallback item key '$FALLBACK_ITEM_KEY' not found") } - fun initialize(assetLoader: AssetLoader) { + fun initialize() { if (_initialized) { Gdx.app.debug(TAG, "Attempted to init when already initialized") return @@ -66,6 +72,10 @@ class GameItemsHolder @Inject constructor( } private fun Map.getOrFallback(key: String, fallback: T, lazyErrorMessage: () -> String): T { + if (!_initialized) { + throw IllegalStateException("GameItemsHolder was not initialized before use") + } + val t = this[key] ?: run { Gdx.app.error(TAG, lazyErrorMessage.invoke()) return fallback @@ -85,6 +95,10 @@ class GameItemsHolder @Inject constructor( } } + fun getBlocksByType(type: Class): List { + return blocksMap.values.filterIsInstance(type) + } + companion object { private const val TAG = "GameItemsHolder" diff --git a/core/src/ru/deadsoftware/cavedroid/game/GameModule.java b/core/src/ru/deadsoftware/cavedroid/game/GameModule.java index a72dbcd..c47a0e1 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/GameModule.java +++ b/core/src/ru/deadsoftware/cavedroid/game/GameModule.java @@ -43,11 +43,14 @@ public class GameModule { @Provides @GameScope - public static GameWorld provideGameWorld(DropController dropController, MobsController mobsController) { - int[][] fm = data != null ? data.retrieveForeMap() : null; - int[][] bm = data != null ? data.retrieveBackMap() : null; + public static GameWorld provideGameWorld(DropController dropController, + MobsController mobsController, + GameItemsHolder gameItemsHolder) { + // TODO: 4/20/24 RE-enable saves +// int[][] fm = data != null ? data.retrieveForeMap() : null; +// int[][] bm = data != null ? data.retrieveBackMap() : null; makeDataNullIfEmpty(); - return new GameWorld(dropController, mobsController, fm, bm); + return new GameWorld(dropController, mobsController, gameItemsHolder, null, null); } } diff --git a/core/src/ru/deadsoftware/cavedroid/game/GamePhysics.java b/core/src/ru/deadsoftware/cavedroid/game/GamePhysics.java index 1ff603c..9edffe4 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/GamePhysics.java +++ b/core/src/ru/deadsoftware/cavedroid/game/GamePhysics.java @@ -8,6 +8,7 @@ import ru.deadsoftware.cavedroid.MainConfig; import ru.deadsoftware.cavedroid.game.mobs.Mob; import ru.deadsoftware.cavedroid.game.mobs.MobsController; import ru.deadsoftware.cavedroid.game.mobs.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.world.GameWorld; @@ -29,16 +30,19 @@ public class GamePhysics { private final MainConfig mMainConfig; private final MobsController mMobsController; private final DropController mDropController; + private final GameItemsHolder mGameItemsHolder; @Inject public GamePhysics(GameWorld gameWorld, MainConfig mainConfig, MobsController mobsController, - DropController dropController) { + DropController dropController, + GameItemsHolder gameItemsHolder) { mGameWorld = gameWorld; mMainConfig = mainConfig; mMobsController = mobsController; mDropController = dropController; + mGameItemsHolder = gameItemsHolder; } /** @@ -50,14 +54,14 @@ public class GamePhysics { int dir = mob.looksLeft() ? 0 : 1; int blX = (int) (mob.getX() + mob.getWidth() * dir - 8 + 16 * dir); int blY = (int) (mob.getY() + mob.getHeight() - 8); - int block = mGameWorld.getForeMap(blX / 16, blY / 16); + Block block = mGameWorld.getForeMap(blX / 16, blY / 16); if (checkColl(new Rectangle(blX, mob.getY() - 18, mob.getWidth(), mob.getHeight()))) { - block = 0; + return false; } - return (block > 0 && GameItems.getBlock(block).toJump() && - (mob.getY() + mob.getHeight()) - GameItems.getBlock(block).getRectangle(blX / 16, blY / 16).y > 8); + return (block.toJump() && + (mob.getY() + mob.getHeight()) - block.getRectangle(blX / 16, blY / 16).y > 8); } private boolean checkColl(Rectangle rect) { @@ -74,12 +78,15 @@ public class GamePhysics { maxY = mGameWorld.getHeight(); } - int block; + Block block; for (int y = minY; y < maxY; y++) { for (int x = minX; x < maxX; x++) { + if (!mGameWorld.hasForeAt(x, y)) { + continue; + } block = mGameWorld.getForeMap(x, y); - if (block > 0 && GameItems.getBlock(block).hasCollision()) { - if (Intersector.overlaps(rect, GameItems.getBlock(block).getRectangle(x, y))) { + if (block.hasCollision()) { + if (Intersector.overlaps(rect, block.getRectangle(x, y))) { return true; } } @@ -89,7 +96,7 @@ public class GamePhysics { return false; } - private int getBlock(Rectangle rect) { + private Block getBlock(Rectangle rect) { return mGameWorld.getForeMap((int) (rect.x + rect.width / 2) / 16, (int) (rect.y + rect.height / 8 * 7) / 16); } @@ -239,7 +246,7 @@ public class GamePhysics { return; } - if (GameItems.isFluid(getBlock(player))) { + if (getBlock(player).isFluid()) { if (mMainConfig.isTouch() && player.getVelocity().x != 0 && !player.swim && !player.isFlyMode()) { player.swim = true; } @@ -266,7 +273,7 @@ public class GamePhysics { mobYColl(player); player.x += player.getVelocity().x * (player.isFlyMode() ? 1.5f : 1) * - (GameItems.isFluid(getBlock(player)) && !player.isFlyMode() ? .8f : 1) * delta; + (getBlock(player).isFluid() && !player.isFlyMode() ? .8f : 1) * delta; mobXColl(player); @@ -277,7 +284,7 @@ public class GamePhysics { } private void mobPhy(Mob mob, float delta) { - if (mob.getType() == Mob.Type.MOB && GameItems.isFluid(getBlock(mob))) { + if (mob.getType() == Mob.Type.MOB && getBlock(mob).isFluid()) { if (mob.getVelocity().y > 32f) { mob.getVelocity().y -= mob.getVelocity().y * 32f * delta; } @@ -320,7 +327,7 @@ public class GamePhysics { for (Iterator it = mMobsController.getMobs().iterator(); it.hasNext(); ) { Mob mob = it.next(); - mob.ai(mGameWorld, delta); + mob.ai(mGameWorld, mGameItemsHolder, delta); mobPhy(mob, delta); if (mob.isDead()) { it.remove(); @@ -329,7 +336,7 @@ public class GamePhysics { playerPhy(player, delta); if (player.isDead()) { - player.respawn(mGameWorld); + player.respawn(mGameWorld, mGameItemsHolder); } } diff --git a/core/src/ru/deadsoftware/cavedroid/game/GameProc.java b/core/src/ru/deadsoftware/cavedroid/game/GameProc.java index 0c3947b..3a22440 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/GameProc.java +++ b/core/src/ru/deadsoftware/cavedroid/game/GameProc.java @@ -42,7 +42,7 @@ public class GameProc implements Disposable { mGameWorldBlocksLogicControllerTask = gameWorldBlocksLogicControllerTask; mGameItemsHolder = gameItemsHolder; - mGameItemsHolder.initialize(assetLoader); + mGameItemsHolder.initialize(); mWorldLogicTimer.scheduleTask(gameWorldFluidsLogicControllerTask, 0, GameWorldFluidsLogicControllerTask.FLUID_UPDATE_INTERVAL_SEC); diff --git a/core/src/ru/deadsoftware/cavedroid/game/GameRenderer.java b/core/src/ru/deadsoftware/cavedroid/game/GameRenderer.java index dd136b8..49b9f0c 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/GameRenderer.java +++ b/core/src/ru/deadsoftware/cavedroid/game/GameRenderer.java @@ -63,9 +63,9 @@ public class GameRenderer extends Renderer { return y * 16 - getCamY(); } - private void drawWreck(int bl) { + private void drawWreck(Block bl) { if (mGameInput.getBlockDamage() > 0) { - int index = 10 * mGameInput.getBlockDamage() / GameItems.getBlock(bl).getHp(); + int index = 10 * mGameInput.getBlockDamage() / bl.getHp(); String key = "break_" + index; if (index > 10 || index < 0) { @@ -79,16 +79,16 @@ public class GameRenderer extends Renderer { private void drawBlock(int x, int y, boolean drawBG) { if (drawBG) { - if ((!mGameWorld.hasForeAt(x, y) || mGameWorld.getForeMapBlock(x, y).isTransparent()) + if ((!mGameWorld.hasForeAt(x, y) || mGameWorld.getForeMap(x, y).isTransparent()) && mGameWorld.hasBackAt(x, y)) { - mGameWorld.getBackMapBlock(x, y).draw(spriter, drawX(x), drawY(y)); + mGameWorld.getBackMap(x, y).draw(spriter, drawX(x), drawY(y)); if (!mGameWorld.hasForeAt(x, y) && x == mGameInput.getCurX() && y == mGameInput.getCurY()) { drawWreck(mGameWorld.getBackMap(mGameInput.getCurX(), mGameInput.getCurY())); } } } - if (mGameWorld.hasForeAt(x, y) && mGameWorld.getForeMapBlock(x, y).isBackground() == drawBG) { - mGameWorld.getForeMapBlock(x, y).draw(spriter, drawX(x), drawY(y)); + if (mGameWorld.hasForeAt(x, y) && mGameWorld.getForeMap(x, y).isBackground() == drawBG) { + mGameWorld.getForeMap(x, y).draw(spriter, drawX(x), drawY(y)); if (x == mGameInput.getCurX() && y == mGameInput.getCurY()) { drawWreck(mGameWorld.getForeMap(mGameInput.getCurX(), mGameInput.getCurY())); } @@ -119,7 +119,7 @@ public class GameRenderer extends Renderer { shaper.setColor(0f, 0f, 0f, .5f); for (int y = minY; y < maxY; y++) { for (int x = minX; x < maxX; x++) { - if ((!mGameWorld.hasForeAt(x, y) || mGameWorld.getForeMapBlock(x, y).isTransparent()) + if ((!mGameWorld.hasForeAt(x, y) || mGameWorld.getForeMap(x, y).isTransparent()) && mGameWorld.hasBackAt(x, y)) { shaper.rect(drawX(x), drawY(y), 16, 16); } @@ -301,7 +301,7 @@ public class GameRenderer extends Renderer { final boolean hasBackMap = mGameWorld.hasBackAt(x, y); if (hasForeMap) { - final Block block = mGameWorld.getForeMapBlock(x, y); + final Block block = mGameWorld.getForeMap(x, y); if (GameItems.isWater(block)) { result = Color.BLUE; @@ -385,10 +385,9 @@ public class GameRenderer extends Renderer { drawString("Swim: " + player.swim, 0, 60); drawString("Mobs: " + mMobsController.getMobs().size(), 0, 70); drawString("Drops: " + mDropController.getSize(), 0, 80); - drawString("Block: " + GameItems.getBlockKey(mGameWorld.getForeMap(mGameInput.getCurX(), mGameInput.getCurY())), 0, 90); + drawString("Block: " + mGameWorld.getForeMap(mGameInput.getCurX(), mGameInput.getCurY()).getParams().getKey(), 0, 90); drawString("Hand: " + GameItems.getItemKey(mMobsController.getPlayer().inventory[mMobsController.getPlayer().slot]), 0, 100); drawString("Game mode: " + player.gameMode, 0, 110); - drawString("Check swim: " + GameItems.isFluid(mGameWorld.getForeMap(player.getMapX(), player.getLowerMapY())), 0, 120); spriter.end(); } diff --git a/core/src/ru/deadsoftware/cavedroid/game/GameSaver.java b/core/src/ru/deadsoftware/cavedroid/game/GameSaver.java index 0e14983..0864a68 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/GameSaver.java +++ b/core/src/ru/deadsoftware/cavedroid/game/GameSaver.java @@ -179,8 +179,9 @@ public class GameSaver { out.writeObject(dropController); out.writeObject(mobsController); out.close(); - saveMap(Gdx.files.absolute(folder + "/saves/foremap.sav"), gameWorld.getFullForeMap()); - saveMap(Gdx.files.absolute(folder + "/saves/backmap.sav"), gameWorld.getFullBackMap()); + // TODO: 4/20/24 save map +// saveMap(Gdx.files.absolute(folder + "/saves/foremap.sav"), gameWorld.getFullForeMap()); +// saveMap(Gdx.files.absolute(folder + "/saves/backmap.sav"), gameWorld.getFullBackMap()); } catch (Exception e) { e.printStackTrace(); } diff --git a/core/src/ru/deadsoftware/cavedroid/game/actions/placeblock/PlaceBlockItemToBackgroundAction.kt b/core/src/ru/deadsoftware/cavedroid/game/actions/placeblock/PlaceBlockItemToBackgroundAction.kt index dd61e0b..bdebfcb 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/actions/placeblock/PlaceBlockItemToBackgroundAction.kt +++ b/core/src/ru/deadsoftware/cavedroid/game/actions/placeblock/PlaceBlockItemToBackgroundAction.kt @@ -10,8 +10,8 @@ class PlaceBlockItemToBackgroundAction @Inject constructor( private val gameWorld: GameWorld, ) : IPlaceBlockAction { - override fun place(item: Item.Placeable, x: Int, y: Int) { - gameWorld.placeToBackground(x, y, item.block.params.id) + override fun place(placeable: Item.Placeable, x: Int, y: Int) { + gameWorld.placeToBackground(x, y, placeable.block) } companion object { diff --git a/core/src/ru/deadsoftware/cavedroid/game/actions/placeblock/PlaceBlockItemToForegroundAction.kt b/core/src/ru/deadsoftware/cavedroid/game/actions/placeblock/PlaceBlockItemToForegroundAction.kt index 75c7bcb..1f74448 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/actions/placeblock/PlaceBlockItemToForegroundAction.kt +++ b/core/src/ru/deadsoftware/cavedroid/game/actions/placeblock/PlaceBlockItemToForegroundAction.kt @@ -10,8 +10,8 @@ class PlaceBlockItemToForegroundAction @Inject constructor( private val gameWorld: GameWorld, ) : IPlaceBlockAction { - override fun place(item: Item.Placeable, x: Int, y: Int) { - gameWorld.placeToForeground(x, y, item.block.params.id) + override fun place(placeable: Item.Placeable, x: Int, y: Int) { + gameWorld.placeToForeground(x, y, placeable.block) } companion object { diff --git a/core/src/ru/deadsoftware/cavedroid/game/actions/updateblock/UpdateGrassAction.kt b/core/src/ru/deadsoftware/cavedroid/game/actions/updateblock/UpdateGrassAction.kt index a9397c9..27005b8 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/actions/updateblock/UpdateGrassAction.kt +++ b/core/src/ru/deadsoftware/cavedroid/game/actions/updateblock/UpdateGrassAction.kt @@ -1,6 +1,6 @@ package ru.deadsoftware.cavedroid.game.actions.updateblock -import ru.deadsoftware.cavedroid.game.GameItems +import ru.deadsoftware.cavedroid.game.GameItemsHolder import ru.deadsoftware.cavedroid.game.GameScope import ru.deadsoftware.cavedroid.game.world.GameWorld import javax.inject.Inject @@ -8,12 +8,13 @@ import javax.inject.Inject @GameScope class UpdateGrassAction @Inject constructor( private val gameWorld: GameWorld, + private val mGameItemsHolder: GameItemsHolder, ) : IUpdateBlockAction { override fun update(x: Int, y: Int) { - val blockOnTop = gameWorld.getForeMapBlock(x, y - 1) + val blockOnTop = gameWorld.getForeMap(x, y - 1) if (blockOnTop.collision || blockOnTop.isFluid()) { - gameWorld.setForeMap(x, y, GameItems.getBlockId("dirt")) + gameWorld.setForeMap(x, y, mGameItemsHolder.getBlock("dirt")) } } diff --git a/core/src/ru/deadsoftware/cavedroid/game/actions/updateblock/UpdateGravelAction.kt b/core/src/ru/deadsoftware/cavedroid/game/actions/updateblock/UpdateGravelAction.kt index 4d39acf..6cc026f 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/actions/updateblock/UpdateGravelAction.kt +++ b/core/src/ru/deadsoftware/cavedroid/game/actions/updateblock/UpdateGravelAction.kt @@ -13,10 +13,10 @@ class UpdateGravelAction @Inject constructor( ) : IUpdateBlockAction { override fun update(x: Int, y: Int) { - val shouldFall = gameWorld.getForeMapBlock(x, y + 1).collision.not() + val shouldFall = gameWorld.getForeMap(x, y + 1).params.hasCollision.not() if (shouldFall) { - gameWorld.setForeMap(x, y, 0) + gameWorld.resetForeMap(x, y) FallingGravel(x * 16f, y * 16f) .apply { attachToController(mobsController) } } diff --git a/core/src/ru/deadsoftware/cavedroid/game/actions/updateblock/UpdateRequiresBlockAction.kt b/core/src/ru/deadsoftware/cavedroid/game/actions/updateblock/UpdateRequiresBlockAction.kt index 2e27373..57172a5 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/actions/updateblock/UpdateRequiresBlockAction.kt +++ b/core/src/ru/deadsoftware/cavedroid/game/actions/updateblock/UpdateRequiresBlockAction.kt @@ -10,7 +10,7 @@ class UpdateRequiresBlockAction @Inject constructor( ) : IUpdateBlockAction { override fun update(x: Int, y: Int) { - if (!gameWorld.getForeMapBlock(x, y + 1).collision) { + if (gameWorld.getForeMap(x, y + 1).params.hasCollision.not()) { gameWorld.destroyForeMap(x, y) } } diff --git a/core/src/ru/deadsoftware/cavedroid/game/actions/updateblock/UpdateSandAction.kt b/core/src/ru/deadsoftware/cavedroid/game/actions/updateblock/UpdateSandAction.kt index c90899c..4a2b58e 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/actions/updateblock/UpdateSandAction.kt +++ b/core/src/ru/deadsoftware/cavedroid/game/actions/updateblock/UpdateSandAction.kt @@ -13,10 +13,10 @@ class UpdateSandAction @Inject constructor( ) : IUpdateBlockAction { override fun update(x: Int, y: Int) { - val shouldFall = gameWorld.getForeMapBlock(x, y + 1).collision.not() + val shouldFall = gameWorld.getForeMap(x, y + 1).params.hasCollision.not() if (shouldFall) { - gameWorld.setForeMap(x, y, 0) + gameWorld.resetForeMap(x, y) FallingSand(x * 16f, y * 16f) .apply { attachToController(mobsController) } } diff --git a/core/src/ru/deadsoftware/cavedroid/game/actions/useitem/UseLavaBucketAction.kt b/core/src/ru/deadsoftware/cavedroid/game/actions/useitem/UseLavaBucketAction.kt index 0bbc042..7256ae9 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/actions/useitem/UseLavaBucketAction.kt +++ b/core/src/ru/deadsoftware/cavedroid/game/actions/useitem/UseLavaBucketAction.kt @@ -1,6 +1,7 @@ package ru.deadsoftware.cavedroid.game.actions.useitem import ru.deadsoftware.cavedroid.game.GameItems +import ru.deadsoftware.cavedroid.game.GameItemsHolder import ru.deadsoftware.cavedroid.game.GameScope import ru.deadsoftware.cavedroid.game.mobs.MobsController import ru.deadsoftware.cavedroid.game.model.item.Item @@ -11,10 +12,11 @@ import javax.inject.Inject class UseLavaBucketAction @Inject constructor( private val gameWorld: GameWorld, private val mobsController: MobsController, + private val gameItemsHolder: GameItemsHolder, ) : IUseItemAction { override fun perform(item: Item.Usable, x: Int, y: Int) { - gameWorld.placeToForeground(x, y, GameItems.getBlockId("lava")) + gameWorld.placeToForeground(x, y, gameItemsHolder.getBlock("lava")) mobsController.player.setCurrentInventorySlotItem(GameItems.getItemId("bucket_empty")) } diff --git a/core/src/ru/deadsoftware/cavedroid/game/actions/useitem/UseWaterBucketAction.kt b/core/src/ru/deadsoftware/cavedroid/game/actions/useitem/UseWaterBucketAction.kt index 9668c4a..32025ce 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/actions/useitem/UseWaterBucketAction.kt +++ b/core/src/ru/deadsoftware/cavedroid/game/actions/useitem/UseWaterBucketAction.kt @@ -1,6 +1,7 @@ package ru.deadsoftware.cavedroid.game.actions.useitem import ru.deadsoftware.cavedroid.game.GameItems +import ru.deadsoftware.cavedroid.game.GameItemsHolder import ru.deadsoftware.cavedroid.game.GameScope import ru.deadsoftware.cavedroid.game.mobs.MobsController import ru.deadsoftware.cavedroid.game.model.item.Item @@ -11,10 +12,11 @@ import javax.inject.Inject class UseWaterBucketAction @Inject constructor( private val gameWorld: GameWorld, private val mobsController: MobsController, + private val gameItemsHolder: GameItemsHolder, ) : IUseItemAction { override fun perform(item: Item.Usable, x: Int, y: Int) { - gameWorld.placeToForeground(x, y, GameItems.getBlockId("water")) + gameWorld.placeToForeground(x, y, gameItemsHolder.getBlock("water")) mobsController.player.setCurrentInventorySlotItem(GameItems.getItemId("bucket_empty")) } diff --git a/core/src/ru/deadsoftware/cavedroid/game/mobs/FallingGravel.java b/core/src/ru/deadsoftware/cavedroid/game/mobs/FallingGravel.java index 81fdb93..e80f91b 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/mobs/FallingGravel.java +++ b/core/src/ru/deadsoftware/cavedroid/game/mobs/FallingGravel.java @@ -3,6 +3,7 @@ package ru.deadsoftware.cavedroid.game.mobs; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.math.Vector2; import ru.deadsoftware.cavedroid.game.GameItems; +import ru.deadsoftware.cavedroid.game.GameItemsHolder; import ru.deadsoftware.cavedroid.game.world.GameWorld; /** @@ -33,9 +34,9 @@ public class FallingGravel extends Mob { } @Override - public void ai(GameWorld gameWorld, float delta) { + public void ai(GameWorld gameWorld, GameItemsHolder gameItemsHolder, float delta) { if (mVelocity.isZero()) { - gameWorld.setForeMap(getMapX(), getMiddleMapY(), 11); + gameWorld.setForeMap(getMapX(), getMiddleMapY(), gameItemsHolder.getBlock("gravel")); kill(); } } diff --git a/core/src/ru/deadsoftware/cavedroid/game/mobs/FallingSand.java b/core/src/ru/deadsoftware/cavedroid/game/mobs/FallingSand.java index 7186b3a..14ec825 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/mobs/FallingSand.java +++ b/core/src/ru/deadsoftware/cavedroid/game/mobs/FallingSand.java @@ -3,6 +3,7 @@ package ru.deadsoftware.cavedroid.game.mobs; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.math.Vector2; import ru.deadsoftware.cavedroid.game.GameItems; +import ru.deadsoftware.cavedroid.game.GameItemsHolder; import ru.deadsoftware.cavedroid.game.world.GameWorld; @@ -34,9 +35,9 @@ public class FallingSand extends Mob { } @Override - public void ai(GameWorld gameWorld, float delta) { + public void ai(GameWorld gameWorld, GameItemsHolder gameItemsHolder, float delta) { if (mVelocity.isZero()) { - gameWorld.setForeMap(getMapX(), getMiddleMapY(), 10); + gameWorld.setForeMap(getMapX(), getMiddleMapY(), gameItemsHolder.getBlock("sand")); kill(); } } diff --git a/core/src/ru/deadsoftware/cavedroid/game/mobs/Mob.java b/core/src/ru/deadsoftware/cavedroid/game/mobs/Mob.java index feb5ceb..394346f 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/mobs/Mob.java +++ b/core/src/ru/deadsoftware/cavedroid/game/mobs/Mob.java @@ -5,6 +5,7 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Rectangle; import com.badlogic.gdx.math.Vector2; +import ru.deadsoftware.cavedroid.game.GameItemsHolder; import ru.deadsoftware.cavedroid.game.world.GameWorld; import java.io.Serializable; @@ -270,7 +271,7 @@ public abstract class Mob extends Rectangle implements Serializable { public abstract void draw(SpriteBatch spriteBatch, float x, float y, float delta); - public abstract void ai(GameWorld gameWorld, float delta); + public abstract void ai(GameWorld gameWorld, GameItemsHolder gameItemsHolder, float delta); public abstract void changeDir(); diff --git a/core/src/ru/deadsoftware/cavedroid/game/mobs/Pig.kt b/core/src/ru/deadsoftware/cavedroid/game/mobs/Pig.kt index 4f9d5fc..b55f429 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/mobs/Pig.kt +++ b/core/src/ru/deadsoftware/cavedroid/game/mobs/Pig.kt @@ -3,6 +3,7 @@ package ru.deadsoftware.cavedroid.game.mobs import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.badlogic.gdx.math.MathUtils import com.badlogic.gdx.math.Vector2 +import ru.deadsoftware.cavedroid.game.GameItemsHolder import ru.deadsoftware.cavedroid.game.world.GameWorld import ru.deadsoftware.cavedroid.misc.utils.drawSprite import ru.deadsoftware.cavedroid.misc.utils.mobs.MobSprites.Pig.getBackgroundLeg @@ -27,7 +28,7 @@ class Pig(x: Float, y: Float) : Mob(x, y, WIDTH, HEIGHT, randomDir(), Type.MOB, velocity.y = JUMP_VELOCITY } - override fun ai(world: GameWorld, delta: Float) { + override fun ai(world: GameWorld, gameItemsHolder: GameItemsHolder, delta: Float) { if (MathUtils.randomBoolean(delta)) { if (velocity.x != 0f) { velocity.x = 0f diff --git a/core/src/ru/deadsoftware/cavedroid/game/mobs/Player.java b/core/src/ru/deadsoftware/cavedroid/game/mobs/Player.java index 6563fd9..d6d848c 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/mobs/Player.java +++ b/core/src/ru/deadsoftware/cavedroid/game/mobs/Player.java @@ -5,6 +5,7 @@ import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.math.MathUtils; import com.badlogic.gdx.math.Vector2; import ru.deadsoftware.cavedroid.game.GameItems; +import ru.deadsoftware.cavedroid.game.GameItemsHolder; import ru.deadsoftware.cavedroid.game.model.item.Item; import ru.deadsoftware.cavedroid.game.objects.Drop; import ru.deadsoftware.cavedroid.game.world.GameWorld; @@ -36,8 +37,8 @@ public class Player extends Mob { swim = false; } - public void respawn(GameWorld gameWorld) { - Vector2 pos = getSpawnPoint(gameWorld); + public void respawn(GameWorld gameWorld, GameItemsHolder itemsHolder) { + Vector2 pos = getSpawnPoint(gameWorld, itemsHolder); this.x = pos.x; this.y = pos.y; mVelocity.setZero(); @@ -55,15 +56,15 @@ public class Player extends Mob { } } - private Vector2 getSpawnPoint(GameWorld gameWorld) { + private Vector2 getSpawnPoint(GameWorld gameWorld, GameItemsHolder itemsHolder) { int y; for (y = 0; y < gameWorld.getHeight(); y++) { if (y == gameWorld.getHeight() - 1) { y = 60; - gameWorld.setForeMap(0, y, 1); + gameWorld.setForeMap(0, y, itemsHolder.getBlock("grass")); break; } - if (gameWorld.hasForeAt(0, y) && gameWorld.getForeMapBlock(0, y).hasCollision()) { + if (gameWorld.hasForeAt(0, y) && gameWorld.getForeMap(0, y).hasCollision()) { break; } } @@ -91,7 +92,7 @@ public class Player extends Mob { } @Override - public void ai(GameWorld gameWorld, float delta) { + public void ai(GameWorld gameWorld, GameItemsHolder gameItemsHolder, float delta) { } @Override diff --git a/core/src/ru/deadsoftware/cavedroid/game/model/block/Block.kt b/core/src/ru/deadsoftware/cavedroid/game/model/block/Block.kt index 4536344..798e3d9 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/model/block/Block.kt +++ b/core/src/ru/deadsoftware/cavedroid/game/model/block/Block.kt @@ -26,7 +26,7 @@ sealed class Block { } val sprite: Sprite - get() = requireNotNull(_sprite) + get() = requireNotNull(_sprite) { "null sprite for block '${params.key}'" } private val currentAnimationFrame: Int get() { @@ -115,14 +115,18 @@ sealed class Block { val fullBlockKey: String, ): Block() - sealed class Fluid: Block() + sealed class Fluid: Block() { + abstract val state: Int + } data class Water( override val params: CommonBlockParams, + override val state: Int, ) : Fluid() data class Lava( override val params: CommonBlockParams, + override val state: Int, ) : Fluid() /* Legacy accessors below */ diff --git a/core/src/ru/deadsoftware/cavedroid/game/model/dto/BlockDto.kt b/core/src/ru/deadsoftware/cavedroid/game/model/dto/BlockDto.kt index 697a042..ae1bfba 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/model/dto/BlockDto.kt +++ b/core/src/ru/deadsoftware/cavedroid/game/model/dto/BlockDto.kt @@ -26,4 +26,5 @@ data class BlockDto( @SerialName("frames") val frames: Int = 0, @SerialName("drop_count") val dropCount: Int = 1, @SerialName("full_block") val fullBlock: String? = null, + @SerialName("state") val state: Int? = null, ) diff --git a/core/src/ru/deadsoftware/cavedroid/game/model/mapper/BlockMapper.kt b/core/src/ru/deadsoftware/cavedroid/game/model/mapper/BlockMapper.kt index 0838491..363801c 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/model/mapper/BlockMapper.kt +++ b/core/src/ru/deadsoftware/cavedroid/game/model/mapper/BlockMapper.kt @@ -18,8 +18,8 @@ class BlockMapper @Inject constructor( val commonBlockParams = mapCommonParams(key, dto) return when (dto.meta) { - "water" -> Water(commonBlockParams) - "lava" -> Lava(commonBlockParams) + "water" -> Water(commonBlockParams, requireNotNull(dto.state)) + "lava" -> Lava(commonBlockParams, requireNotNull(dto.state)) "slab" -> Slab(commonBlockParams, requireNotNull(dto.fullBlock)) else -> Normal(commonBlockParams) } diff --git a/core/src/ru/deadsoftware/cavedroid/game/world/GameWorld.java b/core/src/ru/deadsoftware/cavedroid/game/world/GameWorld.java index d4a66bc..39ae5d3 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/world/GameWorld.java +++ b/core/src/ru/deadsoftware/cavedroid/game/world/GameWorld.java @@ -2,6 +2,7 @@ package ru.deadsoftware.cavedroid.game.world; import kotlin.Pair; import ru.deadsoftware.cavedroid.game.GameItems; +import ru.deadsoftware.cavedroid.game.GameItemsHolder; import ru.deadsoftware.cavedroid.game.GameScope; import ru.deadsoftware.cavedroid.game.mobs.MobsController; import ru.deadsoftware.cavedroid.game.model.block.Block; @@ -16,19 +17,22 @@ public class GameWorld { private final DropController mDropController; private final MobsController mMobsController; + private final GameItemsHolder mGameItemsHolder; private final int mWidth; private final int mHeight; - private final int[][] mForeMap; - private final int[][] mBackMap; + private final Block[][] mForeMap; + private final Block[][] mBackMap; @Inject public GameWorld(DropController dropController, MobsController mobsController, - @CheckForNull int[][] foreMap, - @CheckForNull int[][] backMap) { + GameItemsHolder gameItemsHolder, + @CheckForNull Block[][] foreMap, + @CheckForNull Block[][] backMap) { mDropController = dropController; mMobsController = mobsController; + mGameItemsHolder = gameItemsHolder; boolean isNewGame = foreMap == null || backMap == null; @@ -36,10 +40,10 @@ public class GameWorld { final WorldGeneratorConfig config = WorldGeneratorConfig.Companion.getDefault(); mWidth = config.getWidth(); mHeight = config.getHeight(); - Pair maps = new GameWorldGenerator(config).generate(); + Pair maps = new GameWorldGenerator(config, mGameItemsHolder).generate(); mForeMap = maps.getFirst(); mBackMap = maps.getSecond(); - mMobsController.getPlayer().respawn(this); + mMobsController.getPlayer().respawn(this, mGameItemsHolder); } else { mForeMap = foreMap; mBackMap = backMap; @@ -64,11 +68,11 @@ public class GameWorld { return mHeight * 16f; } - public int[][] getFullForeMap() { + public Block[][] getFullForeMap() { return mForeMap; } - public int[][] getFullBackMap() { + public Block[][] getFullBackMap() { return mBackMap; } @@ -80,8 +84,8 @@ public class GameWorld { return x; } - private int getMap(int x, int y, int layer) { - int map = 0; + private Block getMap(int x, int y, int layer) { + Block map = mGameItemsHolder.getFallbackBlock(); try { x = transformX(x); map = (layer == 0) ? mForeMap[x][y] : mBackMap[x][y]; @@ -90,7 +94,7 @@ public class GameWorld { return map; } - private void setMap(int x, int y, int layer, int value) { + private void setMap(int x, int y, int layer, Block value) { try { x = transformX(x); if (layer == 0) { @@ -103,68 +107,61 @@ public class GameWorld { } public boolean hasForeAt(int x, int y) { - return getMap(x, y, 0) != 0; + return getMap(x, y, 0) != mGameItemsHolder.getFallbackBlock(); } public boolean hasBackAt(int x, int y) { - return getMap(x, y, 1) != 0; + return getMap(x, y, 1) != mGameItemsHolder.getFallbackBlock(); } - public int getForeMap(int x, int y) { + public Block getForeMap(int x, int y) { return getMap(x, y, 0); } - public Block getForeMapBlock(int x, int y) { - return GameItems.getBlock(getMap(x, y, 0)); + public void setForeMap(int x, int y, Block block) { + setMap(x, y, 0, block); } - public void setForeMap(int x, int y, int id) { - setMap(x, y, 0, id); + public void resetForeMap(int x, int y) { + setForeMap(x, y, mGameItemsHolder.getFallbackBlock()); } - public int getBackMap(int x, int y) { + public Block getBackMap(int x, int y) { return getMap(x, y, 1); } - public Block getBackMapBlock(int x, int y) { - return GameItems.getBlock(getMap(x, y, 1)); + public void setBackMap(int x, int y, Block block) { + setMap(x, y, 1, block); } - public void setBackMap(int x, int y, int id) { - setMap(x, y, 1, id); - } - - public void placeToForeground(int x, int y, int value) { - if (!hasForeAt(x, y) || value == 0 || !GameItems.getBlock(getForeMap(x, y)).hasCollision()) { + public void placeToForeground(int x, int y, Block value) { + if (!hasForeAt(x, y) || value == mGameItemsHolder.getFallbackBlock() || !getForeMap(x, y).hasCollision()) { setForeMap(x, y, value); - } else if (GameItems.isSlab(value) && getForeMap(x, y) == value) { - final Block block = GameItems.getBlock(value); - if (block instanceof Block.Slab) { - setForeMap(x, y, GameItems.getBlockId(((Block.Slab) block).getFullBlockKey())); - } + } else if (value instanceof Block.Slab && getForeMap(x, y) == value) { + setForeMap(x, y, mGameItemsHolder.getBlock(((Block.Slab) value).getFullBlockKey())); } } - public void placeToBackground(int x, int y, int value) { - if (value == 0 || (getBackMap(x, y) == 0 && GameItems.getBlock(value).hasCollision()) && - (!GameItems.getBlock(value).isTransparent() || value == 18)) { + public void placeToBackground(int x, int y, Block value) { + if (value == mGameItemsHolder.getFallbackBlock() || (getBackMap(x, y) == mGameItemsHolder.getFallbackBlock() && value.hasCollision()) && + (!value.isTransparent() || value == mGameItemsHolder.getBlock("glass"))) { setBackMap(x, y, value); } } public void destroyForeMap(int x, int y) { - Block block = GameItems.getBlock(getForeMap(x, y)); + Block block = getForeMap(x, y); if (block.hasDrop()) { mDropController.addDrop(transformX(x) * 16 + 4, y * 16 + 4, GameItems.getItemId(block.getDrop())); } - placeToForeground(x, y, 0); + placeToForeground(x, y, mGameItemsHolder.getFallbackBlock()); } public void destroyBackMap(int x, int y) { - Block block = GameItems.getBlock(getBackMap(x, y)); + Block block = getBackMap(x, y); if (block.hasDrop()) { mDropController.addDrop(transformX(x) * 16 + 4, y * 16 + 4, GameItems.getItemId(block.getDrop())); } - placeToBackground(x, y, 0); + placeToBackground(x, y, mGameItemsHolder.getFallbackBlock()); } } \ No newline at end of file diff --git a/core/src/ru/deadsoftware/cavedroid/game/world/GameWorldBlocksLogicControllerTask.kt b/core/src/ru/deadsoftware/cavedroid/game/world/GameWorldBlocksLogicControllerTask.kt index c515330..f0f4af9 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/world/GameWorldBlocksLogicControllerTask.kt +++ b/core/src/ru/deadsoftware/cavedroid/game/world/GameWorldBlocksLogicControllerTask.kt @@ -25,7 +25,7 @@ class GameWorldBlocksLogicControllerTask @Inject constructor( } private fun updateBlock(x: Int, y: Int) { - val block = gameWorld.getForeMapBlock(x, y) + val block = gameWorld.getForeMap(x, y) val blockKey = block.params.key val action = updateBlockActions[blockKey] ?: updateBlockActions.getRequiresBlockAction().takeIf { block.params.requiresBlock } diff --git a/core/src/ru/deadsoftware/cavedroid/game/world/GameWorldFluidsLogicControllerTask.java b/core/src/ru/deadsoftware/cavedroid/game/world/GameWorldFluidsLogicControllerTask.java index d996cf4..ed6b1ec 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/world/GameWorldFluidsLogicControllerTask.java +++ b/core/src/ru/deadsoftware/cavedroid/game/world/GameWorldFluidsLogicControllerTask.java @@ -1,119 +1,161 @@ package ru.deadsoftware.cavedroid.game.world; import com.badlogic.gdx.utils.Timer; +import ru.deadsoftware.cavedroid.game.GameItemsHolder; import ru.deadsoftware.cavedroid.game.GameScope; import ru.deadsoftware.cavedroid.game.mobs.MobsController; +import ru.deadsoftware.cavedroid.game.model.block.Block; +import javax.annotation.CheckForNull; import javax.inject.Inject; -import java.util.Arrays; - -import static ru.deadsoftware.cavedroid.game.GameItems.*; +import java.util.*; @GameScope public class GameWorldFluidsLogicControllerTask extends Timer.Task { public static final float FLUID_UPDATE_INTERVAL_SEC = 0.1f; - private static final int FLUID_STATES = 5; - - private static final int[] WATER_IDS = {8, 60, 61, 62, 63}; - private static final int[] LAVA_IDS = {9, 64, 65, 66, 67}; private final GameWorld mGameWorld; private final MobsController mMobsController; + private final GameItemsHolder mGameItemsHolder; + + private final Map, List> mFluidStatesMap; @Inject GameWorldFluidsLogicControllerTask(GameWorld gameWorld, - MobsController mobsController) { + MobsController mobsController, + GameItemsHolder gameItemsHolder) { mGameWorld = gameWorld; mMobsController = mobsController; + mGameItemsHolder = gameItemsHolder; + + final List waters = mGameItemsHolder.getBlocksByType(Block.Water.class); + waters.sort(Comparator.comparingInt(Block.Water::getState)); + + final List lavas = mGameItemsHolder.getBlocksByType(Block.Lava.class); + lavas.sort(Comparator.comparingInt(Block.Lava::getState)); + + mFluidStatesMap = new HashMap<>(); + mFluidStatesMap.put(Block.Water.class, waters); + mFluidStatesMap.put(Block.Lava.class, lavas); } - private int getBlockState(int id) { - return isWater(id) ? Arrays.binarySearch(WATER_IDS, id) : Arrays.binarySearch(LAVA_IDS, id); + @CheckForNull + private List getFluidStateList(Block.Fluid fluid) { + return mFluidStatesMap.get(fluid.getClass()); } - private int getNextBlockState(int id) { - if (!isFluid(id)) { + private int getCurrentStateIndex(Block.Fluid fluid) { + @CheckForNull final List stateList = getFluidStateList(fluid); + + if (stateList == null) { return -1; } - int state = getBlockState(id); - if (state < FLUID_STATES - 1) { - return state + 1; - } - return -1; + + return stateList.indexOf(fluid); } - private int getNextBlockStateId(int id) { - int nextState = getNextBlockState(id); - if (nextState == -1) { - return 0; + @CheckForNull + private Block.Fluid getNextStateBlock(Block.Fluid fluid) { + @CheckForNull final List stateList = getFluidStateList(fluid); + + if (stateList == null) { + return null; } - if (isWater(id)) { - return WATER_IDS[nextState]; + + int currentState = stateList.indexOf(fluid); + + if (currentState < 0) { + return null; } - return LAVA_IDS[nextState]; - } - private int id(int x, int y) { - return mGameWorld.getForeMap(x, y); - } + int nextState = currentState + 1; + + if (nextState == 1) { + nextState++; + } - private boolean sameFluid(int thisId, int thatId) { - return isFluid(thatId) && isWater(thatId) == isWater(thisId); + if (nextState < stateList.size()) { + return stateList.get(nextState); + } + + return null; } private boolean noFluidNearby(int x, int y) { - return !isFluid(id(x, y - 1)) && - (!isFluid(id(x - 1, y)) || id(x - 1, y) >= id(x, y)) && - (!isFluid(id(x + 1, y)) || id(x + 1, y) >= id(x, y)); + return !mGameWorld.getForeMap(x, y - 1).isFluid() && + (!mGameWorld.getForeMap(x - 1, y).isFluid() || ((Block.Fluid)mGameWorld.getForeMap(x - 1, y)).getState() >= ((Block.Fluid)mGameWorld.getForeMap(x, y)).getState()) && + (!mGameWorld.getForeMap(x + 1, y).isFluid() || ((Block.Fluid)mGameWorld.getForeMap(x + 1, y)).getState() >= ((Block.Fluid)mGameWorld.getForeMap(x, y)).getState()); } private boolean drainFluid(int x, int y) { - if (getBlockState(id(x, y)) > 0) { + final Block block = mGameWorld.getForeMap(x, y); + + if (!(block instanceof Block.Fluid fluid)) { + return true; + } + + if (fluid.getState() > 0) { if (noFluidNearby(x, y)) { - mGameWorld.setForeMap(x, y, getNextBlockStateId(id(x, y))); - } - if (!isFluid(id(x, y))) { - mGameWorld.setForeMap(x, y, 0); - return true; + @CheckForNull final Block nextState = getNextStateBlock(fluid); + if (nextState == null) { + mGameWorld.resetForeMap(x, y); + return true; + } + + mGameWorld.setForeMap(x, y, nextState); } } return false; } - private void flowFluidTo(int thisId, int x, int y, int nextStateId) { - int thatId = id(x, y); - if (fluidCanFlowThere(thisId, thatId)) { - mGameWorld.setForeMap(x, y, nextStateId); - } else if (isWater(thisId) && isLava(thatId)) { - if (getBlockState(thatId) > 0) { - mGameWorld.setForeMap(x, y, 4); //cobblestone + private boolean fluidCanFlowThere(Block.Fluid fluid, Block targetBlock) { + return targetBlock == mGameItemsHolder.getFallbackBlock() || + (!targetBlock.getParams().getHasCollision() && !targetBlock.isFluid()) || + (fluid.getClass() == targetBlock.getClass() && fluid.getState() < ((Block.Fluid)targetBlock).getState()); + } + + private void flowFluidTo(Block.Fluid currentFluid, int x, int y, Block.Fluid nextStateFluid) { + final Block targetBlock = mGameWorld.getForeMap(x, y); + + if (fluidCanFlowThere(currentFluid, targetBlock)) { + mGameWorld.setForeMap(x, y, nextStateFluid); + } else if (currentFluid.isWater() && targetBlock.isLava()) { + if (((Block.Lava)targetBlock).getState() > 0) { + mGameWorld.setForeMap(x, y, mGameItemsHolder.getBlock("cobblestone")); } else { - mGameWorld.setForeMap(x, y, 68); //obsidian + mGameWorld.setForeMap(x, y, mGameItemsHolder.getBlock("obsidian")); } - } else if (isLava(thisId) && isWater(thatId)) { - mGameWorld.setForeMap(x, y, 1); //stone + } else if (currentFluid.isLava() && targetBlock.isWater()) { + mGameWorld.setForeMap(x, y, mGameItemsHolder.getBlock("stone")); } } private void flowFluid(int x, int y) { - int id = id(x, y); - if (getBlockState(id) < FLUID_STATES - 1 && getBlock(id(x, y + 1)).hasCollision()) { - int nextState = getNextBlockState(id); - int nextStateId = getNextBlockStateId(id); - if (nextState == 1) { - nextStateId++; + Block.Fluid fluid = (Block.Fluid) mGameWorld.getForeMap(x, y); + @CheckForNull final List stateList = getFluidStateList(fluid); + + if (stateList == null) { + return; + } + + if (fluid.getState() < stateList.size() - 1 && mGameWorld.getForeMap(x, y + 1).hasCollision()) { + @CheckForNull Block.Fluid nextState = getNextStateBlock(fluid); + + if (nextState == null) { + return; } - flowFluidTo(id, x - 1, y, nextStateId); - flowFluidTo(id, x + 1, y, nextStateId); + + flowFluidTo(fluid, x - 1, y, nextState); + flowFluidTo(fluid, x + 1, y, nextState); } else { - flowFluidTo(id, x, y + 1, isWater(id) ? WATER_IDS[1] : LAVA_IDS[1]); + flowFluidTo(fluid, x, y + 1, stateList.get(1)); } } private void updateFluids(int x, int y) { - if (!isFluid(id(x, y))) { + if (!mGameWorld.getForeMap(x, y).isFluid()) { return; } if (drainFluid(x, y)) { diff --git a/core/src/ru/deadsoftware/cavedroid/game/world/GameWorldGenerator.kt b/core/src/ru/deadsoftware/cavedroid/game/world/GameWorldGenerator.kt index 8776254..b984c4d 100644 --- a/core/src/ru/deadsoftware/cavedroid/game/world/GameWorldGenerator.kt +++ b/core/src/ru/deadsoftware/cavedroid/game/world/GameWorldGenerator.kt @@ -1,6 +1,7 @@ package ru.deadsoftware.cavedroid.game.world -import ru.deadsoftware.cavedroid.game.GameItems +import ru.deadsoftware.cavedroid.game.GameItemsHolder +import ru.deadsoftware.cavedroid.game.model.block.Block import ru.deadsoftware.cavedroid.game.model.world.Biome import ru.deadsoftware.cavedroid.game.model.world.generator.WorldGeneratorConfig import kotlin.math.abs @@ -9,12 +10,13 @@ import kotlin.random.Random class GameWorldGenerator( private val config: WorldGeneratorConfig, + private val gameItemsHolder: GameItemsHolder, ) { private val random = Random(config.seed) - private val foreMap by lazy { Array(config.width) { IntArray(config.height) } } - private val backMap by lazy { Array(config.width) { IntArray(config.height) } } + private val foreMap by lazy { Array(config.width) { Array(config.height) { gameItemsHolder.fallbackBlock } } } + private val backMap by lazy { Array(config.width) { Array(config.height) { gameItemsHolder.fallbackBlock } } } private val heights by lazy { generateHeights() } private val biomesMap by lazy { generateBiomes() } @@ -62,20 +64,20 @@ class GameWorldGenerator( val surfaceHeight = heights[x] - val grassId = GameItems.getBlockId("grass") - val bedrockId = GameItems.getBlockId("bedrock") - val dirtId = GameItems.getBlockId("dirt") - val stoneId = GameItems.getBlockId("stone") + val grass = gameItemsHolder.getBlock("grass") + val bedrock = gameItemsHolder.getBlock("bedrock") + val dirt = gameItemsHolder.getBlock("dirt") + val stone = gameItemsHolder.getBlock("stone") - foreMap[x][surfaceHeight] = grassId - foreMap[x][config.height - 1] = bedrockId - backMap[x][surfaceHeight] = grassId - backMap[x][config.height - 1] = bedrockId + foreMap[x][surfaceHeight] = grass + foreMap[x][config.height - 1] = bedrock + backMap[x][surfaceHeight] = grass + backMap[x][config.height - 1] = bedrock for (y in surfaceHeight + 1 ..< config.height - 1) { foreMap[x][y] = when { - y < surfaceHeight + random.nextInt(5, 8) -> dirtId - else -> stoneId + y < surfaceHeight + random.nextInt(5, 8) -> dirt + else -> stone } backMap[x][y] = foreMap[x][y] } @@ -86,22 +88,22 @@ class GameWorldGenerator( val surfaceHeight = heights[x] - val sandId = GameItems.getBlockId("sand") - val bedrockId = GameItems.getBlockId("bedrock") - val sandstoneId = GameItems.getBlockId("sandstone") - val stoneId = GameItems.getBlockId("stone") + val sand = gameItemsHolder.getBlock("sand") + val bedrock = gameItemsHolder.getBlock("bedrock") + val sandstone = gameItemsHolder.getBlock("sandstone") + val stone = gameItemsHolder.getBlock("stone") - foreMap[x][surfaceHeight] = sandId - foreMap[x][config.height - 1] = bedrockId - backMap[x][surfaceHeight] = sandId - backMap[x][config.height - 1] = bedrockId + foreMap[x][surfaceHeight] = sand + foreMap[x][config.height - 1] = bedrock + backMap[x][surfaceHeight] = sand + backMap[x][config.height - 1] = bedrock for (y in surfaceHeight + 1 ..< config.height - 1) { foreMap[x][y] = when { - y < surfaceHeight + random.nextInt(5, 8) -> sandId - y < surfaceHeight + random.nextInt(0, 2) -> sandstoneId - else -> stoneId + y < surfaceHeight + random.nextInt(5, 8) -> sand + y < surfaceHeight + random.nextInt(0, 2) -> sandstone + else -> stone } backMap[x][y] = foreMap[x][y] } @@ -112,37 +114,36 @@ class GameWorldGenerator( } private fun fillWater() { - val waterId = GameItems.getBlockId("water") + val water = gameItemsHolder.getBlock("water") for (x in 0 ..< config.width) { for (y in config.seaLevel ..< config.height) { - if (foreMap[x][y] != 0) { + if (foreMap[x][y] != gameItemsHolder.fallbackBlock) { break } - foreMap[x][y] = waterId + foreMap[x][y] = water } } } private fun generateCactus(x: Int) { - val cactusId = GameItems.getBlockId("cactus") - val cactusHeight = random.nextInt(5) + val cactus = gameItemsHolder.getBlock("cactus") + val cactusHeight = random.nextInt(3) val h = heights[x] - 1 for (y in h downTo max(0, h - cactusHeight)) { - foreMap[x][y] = cactusId + foreMap[x][y] = cactus } } /** * Generate world */ - fun generate(): Pair, Array> { + fun generate(): Pair>, Array>> { var biome = Biome.PLAINS for (x in 0 until config.width) { - val xHeight = heights[x] biome = biomesMap[x] ?: biome when (biome) {