X-Git-Url: http://deadsoftware.ru/gitweb?a=blobdiff_plain;f=core%2Fsrc%2Fru%2Fdeadsoftware%2Fcavedroid%2Fgame%2Fworld%2FGameWorldFluidsLogicControllerTask.java;h=ed6b1ec634d70cc880ddb81f9d28897eaf811f16;hb=1c004c0ce7e183e773b5b486295c25e39732e899;hp=d996cf42989c41a1025b54fb1c1fd2b77e053cf0;hpb=63ffd8af5e9788f36fc75b6d5c29ae525eb74692;p=cavedroid.git 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)) {