1 package ru
.deadsoftware
.cavedroid
.game
;
3 import java
.util
.Arrays
;
5 import static ru
.deadsoftware
.cavedroid
.GameScreen
.GP
;
6 import static ru
.deadsoftware
.cavedroid
.game
.GameItems
.*;
8 public class GameFluidsThread
extends Thread
{
10 private static final int FLUID_UPDATE_INTERVAL_MS
= 100;
11 private static final int FLUID_STATES
= 5;
13 private static final int[] WATER_IDS
= {8, 60, 61, 62, 63};
14 private static final int[] LAVA_IDS
= {9, 64, 65, 66, 67};
16 private long fluidLastUpdateTimestamp
= 0;
18 private int getBlockState(int id
) {
19 return isWater(id
) ? Arrays
.binarySearch(WATER_IDS
, id
) : Arrays
.binarySearch(LAVA_IDS
, id
);
22 private int getNextBlockState(int id
) {
26 int state
= getBlockState(id
);
27 if (state
< FLUID_STATES
- 1) {
33 private int getNextBlockStateId(int id
) {
34 int nextState
= getNextBlockState(id
);
35 if (nextState
== -1) return 0;
37 return WATER_IDS
[nextState
];
39 return LAVA_IDS
[nextState
];
42 private int id(int x
, int y
) {
43 return GP
.world
.getForeMap(x
, y
);
46 private boolean sameFluid(int thisId
, int thatId
) {
47 return isFluid(thatId
) && isWater(thatId
) == isWater(thisId
);
50 private boolean noFluidNearby(int x
, int y
) {
51 return !isFluid(id(x
, y
- 1)) &&
52 (!isFluid(id(x
- 1, y
)) || id(x
- 1, y
) >= id(x
, y
)) &&
53 (!isFluid(id(x
+ 1, y
)) || id(x
+ 1, y
) >= id(x
, y
));
56 private boolean drainFluid(int x
, int y
) {
57 if (getBlockState(id(x
, y
)) > 0) {
58 if (noFluidNearby(x
, y
)) {
59 GP
.world
.setForeMap(x
, y
, getNextBlockStateId(id(x
, y
)));
61 if (!isFluid(id(x
, y
))) {
62 GP
.world
.setForeMap(x
, y
, 0);
69 private void flowFluidTo(int thisId
, int x
, int y
, int nextStateId
) {
70 int thatId
= id(x
, y
);
71 if (fluidCanFlowThere(thisId
, thatId
)) {
72 GP
.world
.setForeMap(x
, y
, nextStateId
);
73 } else if (isWater(thisId
) && isLava(thatId
)) {
74 if (getBlockState(thatId
) > 0) {
75 GP
.world
.setForeMap(x
, y
, 4); //cobblestone
77 GP
.world
.setForeMap(x
, y
, 68); //obsidian
79 } else if (isLava(thisId
) && isWater(thatId
)) {
80 GP
.world
.setForeMap(x
, y
, 1); //stone
84 private void flowFluid(int x
, int y
) {
86 if (getBlockState(id
) < FLUID_STATES
- 1 && getBlock(id(x
, y
+ 1)).hasCollision()) {
87 int nextState
= getNextBlockState(id
);
88 int nextStateId
= getNextBlockStateId(id
);
92 flowFluidTo(id
, x
- 1, y
, nextStateId
);
93 flowFluidTo(id
, x
+ 1, y
, nextStateId
);
95 flowFluidTo(id
, x
, y
+ 1, isWater(id
) ? WATER_IDS
[1] : LAVA_IDS
[1]);
100 private void updateFluids(int x
, int y
) {
101 if (!isFluid(id(x
, y
))) return;
102 if (drainFluid(x
, y
)) return;
106 private void fluidUpdater() {
107 int midScreen
= (int) (GP
.renderer
.getCamX() + GP
.renderer
.getWidth() / 2) / 16;
108 for (int y
= GP
.world
.getHeight() - 1; y
>= 0; y
--) {
109 for (int x
= 0; x
<= GP
.world
.getWidth() / 2; x
++) {
110 updateFluids(midScreen
+ x
, y
);
111 updateFluids(midScreen
- x
, y
);
116 private boolean timeToUpdate() {
117 if (System
.currentTimeMillis() - fluidLastUpdateTimestamp
>= FLUID_UPDATE_INTERVAL_MS
) {
118 fluidLastUpdateTimestamp
= System
.currentTimeMillis();
126 while (!this.isInterrupted()) {
127 if (timeToUpdate()) {