1 package ru
.deadsoftware
.cavedroid
.game
.world
;
3 import com
.badlogic
.gdx
.utils
.Timer
;
4 import ru
.deadsoftware
.cavedroid
.game
.GameItemsHolder
;
5 import ru
.deadsoftware
.cavedroid
.game
.GameScope
;
6 import ru
.deadsoftware
.cavedroid
.game
.mobs
.MobsController
;
7 import ru
.deadsoftware
.cavedroid
.game
.model
.block
.Block
;
9 import javax
.annotation
.CheckForNull
;
10 import javax
.inject
.Inject
;
14 public class GameWorldFluidsLogicControllerTask
extends Timer
.Task
{
16 public static final float FLUID_UPDATE_INTERVAL_SEC
= 0.1f;
18 private final GameWorld mGameWorld
;
19 private final MobsController mMobsController
;
20 private final GameItemsHolder mGameItemsHolder
;
22 private final Map
<Class
<?
extends Block
.Fluid
>, List
<?
extends Block
.Fluid
>> mFluidStatesMap
;
25 GameWorldFluidsLogicControllerTask(GameWorld gameWorld
,
26 MobsController mobsController
,
27 GameItemsHolder gameItemsHolder
) {
28 mGameWorld
= gameWorld
;
29 mMobsController
= mobsController
;
30 mGameItemsHolder
= gameItemsHolder
;
32 final List
<Block
.Water
> waters
= mGameItemsHolder
.getBlocksByType(Block
.Water
.class);
33 waters
.sort(Comparator
.comparingInt(Block
.Water
::getState
));
35 final List
<Block
.Lava
> lavas
= mGameItemsHolder
.getBlocksByType(Block
.Lava
.class);
36 lavas
.sort(Comparator
.comparingInt(Block
.Lava
::getState
));
38 mFluidStatesMap
= new HashMap
<>();
39 mFluidStatesMap
.put(Block
.Water
.class, waters
);
40 mFluidStatesMap
.put(Block
.Lava
.class, lavas
);
44 private List
<?
extends Block
.Fluid
> getFluidStateList(Block
.Fluid fluid
) {
45 return mFluidStatesMap
.get(fluid
.getClass());
48 private int getCurrentStateIndex(Block
.Fluid fluid
) {
49 @CheckForNull final List
<?
extends Block
.Fluid
> stateList
= getFluidStateList(fluid
);
51 if (stateList
== null) {
55 return stateList
.indexOf(fluid
);
59 private Block
.Fluid
getNextStateBlock(Block
.Fluid fluid
) {
60 @CheckForNull final List
<?
extends Block
.Fluid
> stateList
= getFluidStateList(fluid
);
62 if (stateList
== null) {
66 int currentState
= stateList
.indexOf(fluid
);
68 if (currentState
< 0) {
72 int nextState
= currentState
+ 1;
78 if (nextState
< stateList
.size()) {
79 return stateList
.get(nextState
);
85 private boolean noFluidNearby(int x
, int y
) {
86 return !mGameWorld
.getForeMap(x
, y
- 1).isFluid() &&
87 (!mGameWorld
.getForeMap(x
- 1, y
).isFluid() || ((Block
.Fluid
)mGameWorld
.getForeMap(x
- 1, y
)).getState() >= ((Block
.Fluid
)mGameWorld
.getForeMap(x
, y
)).getState()) &&
88 (!mGameWorld
.getForeMap(x
+ 1, y
).isFluid() || ((Block
.Fluid
)mGameWorld
.getForeMap(x
+ 1, y
)).getState() >= ((Block
.Fluid
)mGameWorld
.getForeMap(x
, y
)).getState());
91 private boolean drainFluid(int x
, int y
) {
92 final Block block
= mGameWorld
.getForeMap(x
, y
);
94 if (!(block
instanceof Block
.Fluid fluid
)) {
98 if (fluid
.getState() > 0) {
99 if (noFluidNearby(x
, y
)) {
100 @CheckForNull final Block nextState
= getNextStateBlock(fluid
);
101 if (nextState
== null) {
102 mGameWorld
.resetForeMap(x
, y
);
106 mGameWorld
.setForeMap(x
, y
, nextState
);
112 private boolean fluidCanFlowThere(Block
.Fluid fluid
, Block targetBlock
) {
113 return targetBlock
== mGameItemsHolder
.getFallbackBlock() ||
114 (!targetBlock
.getParams().getHasCollision() && !targetBlock
.isFluid()) ||
115 (fluid
.getClass() == targetBlock
.getClass() && fluid
.getState() < ((Block
.Fluid
)targetBlock
).getState());
118 private void flowFluidTo(Block
.Fluid currentFluid
, int x
, int y
, Block
.Fluid nextStateFluid
) {
119 final Block targetBlock
= mGameWorld
.getForeMap(x
, y
);
121 if (fluidCanFlowThere(currentFluid
, targetBlock
)) {
122 mGameWorld
.setForeMap(x
, y
, nextStateFluid
);
123 } else if (currentFluid
.isWater() && targetBlock
.isLava()) {
124 if (((Block
.Lava
)targetBlock
).getState() > 0) {
125 mGameWorld
.setForeMap(x
, y
, mGameItemsHolder
.getBlock("cobblestone"));
127 mGameWorld
.setForeMap(x
, y
, mGameItemsHolder
.getBlock("obsidian"));
129 } else if (currentFluid
.isLava() && targetBlock
.isWater()) {
130 mGameWorld
.setForeMap(x
, y
, mGameItemsHolder
.getBlock("stone"));
134 private void flowFluid(int x
, int y
) {
135 Block
.Fluid fluid
= (Block
.Fluid
) mGameWorld
.getForeMap(x
, y
);
136 @CheckForNull final List
<?
extends Block
.Fluid
> stateList
= getFluidStateList(fluid
);
138 if (stateList
== null) {
142 if (fluid
.getState() < stateList
.size() - 1 && mGameWorld
.getForeMap(x
, y
+ 1).hasCollision()) {
143 @CheckForNull Block
.Fluid nextState
= getNextStateBlock(fluid
);
145 if (nextState
== null) {
149 flowFluidTo(fluid
, x
- 1, y
, nextState
);
150 flowFluidTo(fluid
, x
+ 1, y
, nextState
);
152 flowFluidTo(fluid
, x
, y
+ 1, stateList
.get(1));
157 private void updateFluids(int x
, int y
) {
158 if (!mGameWorld
.getForeMap(x
, y
).isFluid()) {
161 if (drainFluid(x
, y
)) {
167 private void fluidUpdater() {
168 int midScreen
= (int) mMobsController
.getPlayer().x
/ 16;
169 for (int y
= mGameWorld
.getHeight() - 1; y
>= 0; y
--) {
170 for (int x
= 0; x
<= Math
.min(mGameWorld
.getWidth() / 2, 32); x
++) {
171 updateFluids(midScreen
+ x
, y
);
172 updateFluids(midScreen
- x
, y
);