[cavedroid.git] / core / src / ru / deadsoftware / cavedroid / game / world / GameWorldFluidsLogicControllerTask.java
diff --git a/core/src/ru/deadsoftware/cavedroid/game/world/GameWorldFluidsLogicControllerTask.java b/core/src/ru/deadsoftware/cavedroid/game/world/GameWorldFluidsLogicControllerTask.java
index d996cf42989c41a1025b54fb1c1fd2b77e053cf0..ed6b1ec634d70cc880ddb81f9d28897eaf811f16 100644 (file)
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<Class<? extends Block.Fluid>, List<? extends Block.Fluid>> mFluidStatesMap;
@Inject
GameWorldFluidsLogicControllerTask(GameWorld gameWorld,
- MobsController mobsController) {
+ MobsController mobsController,
+ GameItemsHolder gameItemsHolder) {
mGameWorld = gameWorld;
mMobsController = mobsController;
+ mGameItemsHolder = gameItemsHolder;
+
+ final List<Block.Water> waters = mGameItemsHolder.getBlocksByType(Block.Water.class);
+ waters.sort(Comparator.comparingInt(Block.Water::getState));
+
+ final List<Block.Lava> 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<? extends Block.Fluid> 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<? extends Block.Fluid> 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<? extends Block.Fluid> 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<? extends Block.Fluid> 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)) {