mirror of
https://github.com/array-in-a-matrix/brainwine.git
synced 2025-04-02 11:11:58 -04:00
Moved chunk code to ChunkManager
This commit is contained in:
parent
8b9c978d1b
commit
565301f528
2 changed files with 141 additions and 95 deletions
|
@ -7,6 +7,12 @@ import java.io.FileInputStream;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.RandomAccessFile;
|
import java.io.RandomAccessFile;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
@ -17,6 +23,7 @@ import org.msgpack.jackson.dataformat.MessagePackFactory;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.databind.module.SimpleModule;
|
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||||
|
|
||||||
|
import brainwine.gameserver.entity.player.Player;
|
||||||
import brainwine.gameserver.serialization.BlockDeserializer;
|
import brainwine.gameserver.serialization.BlockDeserializer;
|
||||||
import brainwine.gameserver.serialization.BlockSerializer;
|
import brainwine.gameserver.serialization.BlockSerializer;
|
||||||
import brainwine.gameserver.util.ZipUtils;
|
import brainwine.gameserver.util.ZipUtils;
|
||||||
|
@ -29,6 +36,7 @@ public class ChunkManager {
|
||||||
.registerModule(new SimpleModule()
|
.registerModule(new SimpleModule()
|
||||||
.addDeserializer(Block.class, BlockDeserializer.INSTANCE)
|
.addDeserializer(Block.class, BlockDeserializer.INSTANCE)
|
||||||
.addSerializer(BlockSerializer.INSTANCE));
|
.addSerializer(BlockSerializer.INSTANCE));
|
||||||
|
private final Map<Integer, Chunk> chunks = new HashMap<>();
|
||||||
private final Zone zone;
|
private final Zone zone;
|
||||||
private final File blocksFile;
|
private final File blocksFile;
|
||||||
private RandomAccessFile file;
|
private RandomAccessFile file;
|
||||||
|
@ -84,32 +92,35 @@ public class ChunkManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Chunk loadChunk(int index) {
|
public void saveChunks() {
|
||||||
try {
|
List<Chunk> inactiveChunks = new ArrayList<>();
|
||||||
if(file == null) {
|
|
||||||
file = new RandomAccessFile(blocksFile, "rw");
|
|
||||||
}
|
|
||||||
|
|
||||||
file.seek(dataOffset + index * allocSize);
|
|
||||||
byte[] bytes = new byte[file.readShort()];
|
|
||||||
file.read(bytes);
|
|
||||||
return mapper.readValue(ZipUtils.inflateBytes(bytes), Chunk.class);
|
|
||||||
} catch(Exception e) {
|
|
||||||
logger.error("Could not load chunk {} of zone {}", index, zone.getDocumentId(), e);
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void saveModifiedChunks() {
|
|
||||||
for(Chunk chunk : zone.getChunks()) {
|
for(Chunk chunk : zone.getChunks()) {
|
||||||
if(chunk.isModified()) {
|
if(chunk.isModified()) {
|
||||||
saveChunk(chunk);
|
saveChunk(chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean active = false;
|
||||||
|
|
||||||
|
for(Player player : zone.getPlayers()) {
|
||||||
|
if(player.isChunkActive(chunk)) {
|
||||||
|
active = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!active) {
|
||||||
|
inactiveChunks.add(chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(Chunk chunk : inactiveChunks) {
|
||||||
|
chunks.remove(getChunkIndex(chunk.getX(), chunk.getY()));
|
||||||
|
zone.onChunkUnloaded(chunk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void saveChunk(Chunk chunk) {
|
private void saveChunk(Chunk chunk) {
|
||||||
int index = zone.getChunkIndex(chunk.getX(), chunk.getY());
|
int index = zone.getChunkIndex(chunk.getX(), chunk.getY());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -131,4 +142,68 @@ public class ChunkManager {
|
||||||
logger.error("Could not save chunk {} of zone {}", index, zone.getDocumentId(), e);
|
logger.error("Could not save chunk {} of zone {}", index, zone.getDocumentId(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Chunk loadChunk(int index) {
|
||||||
|
try {
|
||||||
|
if(file == null) {
|
||||||
|
file = new RandomAccessFile(blocksFile, "rw");
|
||||||
|
}
|
||||||
|
|
||||||
|
file.seek(dataOffset + index * allocSize);
|
||||||
|
byte[] bytes = new byte[file.readShort()];
|
||||||
|
file.read(bytes);
|
||||||
|
return mapper.readValue(ZipUtils.inflateBytes(bytes), Chunk.class);
|
||||||
|
} catch(Exception e) {
|
||||||
|
logger.error("Could not load chunk {} of zone {}", index, zone.getDocumentId(), e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void putChunk(int index, Chunk chunk) {
|
||||||
|
if(!chunks.containsKey(index) && isChunkIndexInBounds(index)) {
|
||||||
|
chunk.setModified(true);
|
||||||
|
chunks.put(index, chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isChunkLoaded(int x, int y) {
|
||||||
|
return isChunkLoaded(getChunkIndex(x, y));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isChunkLoaded(int index) {
|
||||||
|
return chunks.containsKey(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isChunkIndexInBounds(int index) {
|
||||||
|
return index >= 0 && index < zone.getNumChunksWidth() * zone.getNumChunksHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getChunkIndex(int x, int y) {
|
||||||
|
return y / zone.getChunkHeight() * zone.getNumChunksWidth() + x / zone.getChunkWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Chunk getChunk(int x, int y) {
|
||||||
|
return getChunk(getChunkIndex(x, y));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Chunk getChunk(int index) {
|
||||||
|
if(!isChunkIndexInBounds(index)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Chunk chunk = chunks.get(index);
|
||||||
|
|
||||||
|
if(chunk == null) {
|
||||||
|
chunk = loadChunk(index);
|
||||||
|
chunks.put(index, chunk);
|
||||||
|
zone.onChunkLoaded(chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
return chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<Chunk> getChunks() {
|
||||||
|
return Collections.unmodifiableCollection(chunks.values());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,10 +8,8 @@ import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -71,7 +69,6 @@ public class Zone {
|
||||||
private final Set<Integer> pendingSunlight = new HashSet<>();
|
private final Set<Integer> pendingSunlight = new HashSet<>();
|
||||||
private final Map<Integer, Entity> entities = new HashMap<>();
|
private final Map<Integer, Entity> entities = new HashMap<>();
|
||||||
private final List<Player> players = new ArrayList<>();
|
private final List<Player> players = new ArrayList<>();
|
||||||
private final Map<Integer, Chunk> chunks = new HashMap<>();
|
|
||||||
private final Map<String, Integer> dungeons = new HashMap<>();
|
private final Map<String, Integer> dungeons = new HashMap<>();
|
||||||
private final Map<Integer, MetaBlock> metaBlocks = new HashMap<>();
|
private final Map<Integer, MetaBlock> metaBlocks = new HashMap<>();
|
||||||
private final Map<Integer, MetaBlock> globalMetaBlocks = new HashMap<>();
|
private final Map<Integer, MetaBlock> globalMetaBlocks = new HashMap<>();
|
||||||
|
@ -144,11 +141,6 @@ public class Zone {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void saveModifiedChunks() {
|
|
||||||
chunkManager.saveModifiedChunks();
|
|
||||||
removeInactiveChunks();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a message to each player in this zone.
|
* Sends a message to each player in this zone.
|
||||||
*
|
*
|
||||||
|
@ -678,75 +670,8 @@ public class Zone {
|
||||||
return x >= 0 && y >= 0 && x < width && y < height;
|
return x >= 0 && y >= 0 && x < width && y < height;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeInactiveChunks() {
|
protected void onChunkLoaded(Chunk chunk) {
|
||||||
Iterator<Entry<Integer, Chunk>> iterator = chunks.entrySet().iterator();
|
// Update sunlight
|
||||||
|
|
||||||
while(iterator.hasNext()) {
|
|
||||||
Entry<Integer, Chunk> entry = iterator.next();
|
|
||||||
Chunk chunk = entry.getValue();
|
|
||||||
boolean active = false;
|
|
||||||
|
|
||||||
for(Player player : players) {
|
|
||||||
if(player.isChunkActive(chunk)) {
|
|
||||||
active = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!active) {
|
|
||||||
iterator.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isChunkIndexInBounds(int index) {
|
|
||||||
return index >= 0 && index < numChunksWidth * numChunksHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isChunkLoaded(int x, int y) {
|
|
||||||
return isChunkLoaded(getChunkIndex(x, y));
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isChunkLoaded(int index) {
|
|
||||||
return chunks.containsKey(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void putChunk(int index, Chunk chunk) {
|
|
||||||
if(!chunks.containsKey(index) && isChunkIndexInBounds(index)) {
|
|
||||||
chunk.setModified(true);
|
|
||||||
chunks.put(index, chunk);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getChunkIndex(int x, int y) {
|
|
||||||
return y / chunkHeight * numChunksWidth + x / chunkWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Chunk getChunk(int x, int y) {
|
|
||||||
return getChunk(getChunkIndex(x, y));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Chunk getChunk(int index) {
|
|
||||||
if(!isChunkIndexInBounds(index)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Chunk chunk = chunks.get(index);
|
|
||||||
|
|
||||||
if(chunk == null) {
|
|
||||||
chunk = chunkManager.loadChunk(index);
|
|
||||||
tryRecalculatePendingSunlight(chunk);
|
|
||||||
chunks.put(index, chunk);
|
|
||||||
}
|
|
||||||
|
|
||||||
return chunk;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Collection<Chunk> getChunks() {
|
|
||||||
return chunks.values();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void tryRecalculatePendingSunlight(Chunk chunk) {
|
|
||||||
if(!pendingSunlight.isEmpty()) {
|
if(!pendingSunlight.isEmpty()) {
|
||||||
int chunkX = chunk.getX();
|
int chunkX = chunk.getX();
|
||||||
|
|
||||||
|
@ -757,6 +682,52 @@ public class Zone {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO more chunk related thingies, such as surface calculations,
|
||||||
|
// entity spawning and block indexing
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onChunkUnloaded(Chunk chunk) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
public void saveChunks() {
|
||||||
|
chunkManager.saveChunks();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should only be called by zone gen.
|
||||||
|
*/
|
||||||
|
public void putChunk(int index, Chunk chunk) {
|
||||||
|
chunkManager.putChunk(index, chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isChunkLoaded(int x, int y) {
|
||||||
|
return chunkManager.isChunkLoaded(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isChunkLoaded(int index) {
|
||||||
|
return chunkManager.isChunkLoaded(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isChunkIndexInBounds(int index) {
|
||||||
|
return chunkManager.isChunkIndexInBounds(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getChunkIndex(int x, int y) {
|
||||||
|
return chunkManager.getChunkIndex(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Chunk getChunk(int x, int y) {
|
||||||
|
return chunkManager.getChunk(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Chunk getChunk(int index) {
|
||||||
|
return chunkManager.getChunk(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<Chunk> getChunks() {
|
||||||
|
return chunkManager.getChunks();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSurface(int x, int surface) {
|
public void setSurface(int x, int surface) {
|
||||||
|
|
Loading…
Add table
Reference in a new issue