Removed useless "multiplayer" crap and converted to singleplayer
This commit is contained in:
@@ -5,9 +5,11 @@ import static org.lwjgl.opengl.GL11.*;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import mightypork.gamecore.audio.players.EffectPlayer;
|
||||
import mightypork.gamecore.render.textures.FilterMode;
|
||||
import mightypork.gamecore.render.textures.GLTexture;
|
||||
import mightypork.gamecore.render.textures.TxQuad;
|
||||
import mightypork.rogue.Res;
|
||||
import mightypork.util.constraints.rect.Rect;
|
||||
import mightypork.util.constraints.rect.caching.RectDigest;
|
||||
import mightypork.util.constraints.vect.Vect;
|
||||
@@ -230,6 +232,8 @@ public class Render {
|
||||
}
|
||||
|
||||
private static int pushed = 0;
|
||||
/** Can be used to avoid texture binding and glBegin/glEnd in textured quads */
|
||||
public static boolean batchTexturedQuadMode;
|
||||
|
||||
|
||||
/**
|
||||
@@ -432,14 +436,14 @@ public class Render {
|
||||
*/
|
||||
public static void quadTextured(Rect quad, Rect uvs, GLTexture texture, Color tint)
|
||||
{
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
|
||||
texture.bind();
|
||||
if (!batchTexturedQuadMode) {
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
texture.bind();
|
||||
glBegin(GL_QUADS);
|
||||
}
|
||||
|
||||
setColor(tint);
|
||||
|
||||
glBegin(GL_QUADS);
|
||||
|
||||
final RectDigest q = quad.digest();
|
||||
final RectDigest u = uvs.digest();
|
||||
|
||||
@@ -458,7 +462,8 @@ public class Render {
|
||||
|
||||
glTexCoord2d(u.left * w, u.top * h);
|
||||
glVertex2d(q.left, q.top);
|
||||
glEnd();
|
||||
|
||||
if (!batchTexturedQuadMode) glEnd();
|
||||
}
|
||||
|
||||
|
||||
@@ -544,4 +549,18 @@ public class Render {
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
|
||||
public static void enterBatchTexturedQuadMode(GLTexture texture)
|
||||
{
|
||||
texture.bind();
|
||||
GL11.glBegin(GL11.GL_QUADS);
|
||||
batchTexturedQuadMode = true;
|
||||
}
|
||||
|
||||
|
||||
public static void leaveBatchTexturedQuadMode()
|
||||
{
|
||||
GL11.glEnd();
|
||||
batchTexturedQuadMode = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import mightypork.gamecore.render.fonts.GLFont;
|
||||
import mightypork.gamecore.render.textures.DeferredTexture;
|
||||
import mightypork.gamecore.render.textures.FilterMode;
|
||||
import mightypork.util.constraints.vect.Vect;
|
||||
import mightypork.util.constraints.vect.VectConst;
|
||||
@@ -374,6 +375,8 @@ public class CachedFont implements GLFont {
|
||||
{
|
||||
GLUtils.checkGLContext();
|
||||
|
||||
DeferredTexture.lastBind = null; // needs rebind.
|
||||
|
||||
// PUSH
|
||||
glPushAttrib(GL_ENABLE_BIT);
|
||||
|
||||
|
||||
@@ -19,6 +19,8 @@ import org.lwjgl.opengl.GL11;
|
||||
@MustLoadInMainThread
|
||||
public class DeferredTexture extends DeferredResource implements GLTexture {
|
||||
|
||||
public static DeferredTexture lastBind = null;
|
||||
|
||||
private org.newdawn.slick.opengl.Texture backingTexture;
|
||||
private FilterMode filter = FilterMode.NEAREST;
|
||||
private WrapMode wrap = WrapMode.CLAMP;
|
||||
@@ -70,15 +72,19 @@ public class DeferredTexture extends DeferredResource implements GLTexture {
|
||||
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||
|
||||
GL11.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_MODULATE);
|
||||
|
||||
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, wrap.num);
|
||||
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, wrap.num);
|
||||
|
||||
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, filter.num);
|
||||
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, filter.num);
|
||||
|
||||
GL11.glBindTexture(GL11.GL_TEXTURE_2D, getTextureID());
|
||||
if (lastBind != this) {
|
||||
lastBind = this;
|
||||
|
||||
GL11.glTexEnvf(GL11.GL_TEXTURE_ENV, GL11.GL_TEXTURE_ENV_MODE, GL11.GL_MODULATE);
|
||||
|
||||
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, wrap.num);
|
||||
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, wrap.num);
|
||||
|
||||
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, filter.num);
|
||||
GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, filter.num);
|
||||
|
||||
GL11.glBindTexture(GL11.GL_TEXTURE_2D, getTextureID());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -22,9 +22,9 @@ import mightypork.rogue.screens.main_menu.ScreenMainMenu;
|
||||
import mightypork.rogue.screens.test_bouncyboxes.ScreenTestBouncy;
|
||||
import mightypork.rogue.screens.test_cat_sound.ScreenTestCat;
|
||||
import mightypork.rogue.screens.test_render.ScreenTestRender;
|
||||
import mightypork.rogue.world.PlayerEntity;
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.item.Item;
|
||||
import mightypork.rogue.world.map.Level;
|
||||
import mightypork.rogue.world.level.Level;
|
||||
import mightypork.rogue.world.tile.Tile;
|
||||
import mightypork.util.control.eventbus.EventBus;
|
||||
import mightypork.util.control.eventbus.events.Event;
|
||||
@@ -110,7 +110,7 @@ public final class App extends BaseApp {
|
||||
Ion.registerBinary(Tile.ION_MARK, Tile.class);
|
||||
Ion.registerBinary(Item.ION_MARK, Item.class);
|
||||
Ion.registerBinary(Level.ION_MARK, Level.class);
|
||||
Ion.registerBinary(Level.ION_MARK, PlayerEntity.class);
|
||||
Ion.registerBinary(Entity.ION_MARK, Entity.class);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ public final class Res {
|
||||
textures.addQuad("xp_off", gui.makeQuad(.5, 1.5, .5, .5));
|
||||
textures.addQuad("panel", gui.makeQuad(0, 3.75, 4, .25));
|
||||
|
||||
texture = textures.loadTexture("tiles", "/res/img/map_tiles.png", FilterMode.NEAREST, WrapMode.CLAMP);
|
||||
texture = textures.loadTexture("tiles", "/res/img/tiles.png", FilterMode.NEAREST, WrapMode.CLAMP);
|
||||
final QuadGrid tiles = texture.grid(32, 32);
|
||||
|
||||
textures.addSheet("tile.wall.mossy_bricks", tiles.makeSheet(4, 0, 7, 1));
|
||||
|
||||
@@ -7,9 +7,6 @@ import java.util.Random;
|
||||
|
||||
import mightypork.gamecore.gui.screens.Screen;
|
||||
import mightypork.gamecore.gui.screens.ScreenLayer;
|
||||
import mightypork.gamecore.input.InputSystem;
|
||||
import mightypork.gamecore.input.KeyStroke;
|
||||
import mightypork.gamecore.input.Keys;
|
||||
import mightypork.rogue.Paths;
|
||||
import mightypork.rogue.world.MapGenerator;
|
||||
import mightypork.rogue.world.World;
|
||||
@@ -28,7 +25,7 @@ public class WorldLayer extends ScreenLayer {
|
||||
final World w = MapGenerator.createWorld(rand.nextLong());
|
||||
|
||||
try {
|
||||
Ion.toFile(new File(Paths.WORKDIR,"test-world.ion"), w);
|
||||
Ion.toFile(new File(Paths.WORKDIR, "test-world.ion"), w);
|
||||
} catch (final IOException e) {
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
@@ -49,63 +46,63 @@ public class WorldLayer extends ScreenLayer {
|
||||
wr.setRect(root);
|
||||
root.add(wr);
|
||||
|
||||
bindKey(new KeyStroke(true, Keys.LEFT), new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
w.getPlayer().walk(-1, 0);
|
||||
}
|
||||
});
|
||||
bindKey(new KeyStroke(true, Keys.RIGHT), new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
w.getPlayer().walk(1, 0);
|
||||
}
|
||||
});
|
||||
bindKey(new KeyStroke(true, Keys.UP), new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
w.getPlayer().walk(0, -1);
|
||||
}
|
||||
});
|
||||
bindKey(new KeyStroke(true, Keys.DOWN), new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
w.getPlayer().walk(0, 1);
|
||||
}
|
||||
});
|
||||
bindKey(new KeyStroke(true, Keys.SPACE), new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
w.getPlayer().walk(5, 5);
|
||||
}
|
||||
});
|
||||
|
||||
w.getPlayer().setMoveListener(new Runnable() {
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if (InputSystem.isKeyDown(Keys.LEFT)) {
|
||||
w.getPlayer().walk(-1, 0);
|
||||
} else if (InputSystem.isKeyDown(Keys.RIGHT)) {
|
||||
w.getPlayer().walk(1, 0);
|
||||
} else if (InputSystem.isKeyDown(Keys.UP)) {
|
||||
w.getPlayer().walk(0, -1);
|
||||
} else if (InputSystem.isKeyDown(Keys.DOWN)) {
|
||||
w.getPlayer().walk(0, 1);
|
||||
}
|
||||
}
|
||||
});
|
||||
// bindKey(new KeyStroke(true, Keys.LEFT), new Runnable() {
|
||||
//
|
||||
// @Override
|
||||
// public void run()
|
||||
// {
|
||||
// w.getPlayer().walk(-1, 0);
|
||||
// }
|
||||
// });
|
||||
// bindKey(new KeyStroke(true, Keys.RIGHT), new Runnable() {
|
||||
//
|
||||
// @Override
|
||||
// public void run()
|
||||
// {
|
||||
// w.getPlayer().walk(1, 0);
|
||||
// }
|
||||
// });
|
||||
// bindKey(new KeyStroke(true, Keys.UP), new Runnable() {
|
||||
//
|
||||
// @Override
|
||||
// public void run()
|
||||
// {
|
||||
// w.getPlayer().walk(0, -1);
|
||||
// }
|
||||
// });
|
||||
// bindKey(new KeyStroke(true, Keys.DOWN), new Runnable() {
|
||||
//
|
||||
// @Override
|
||||
// public void run()
|
||||
// {
|
||||
// w.getPlayer().walk(0, 1);
|
||||
// }
|
||||
// });
|
||||
// bindKey(new KeyStroke(true, Keys.SPACE), new Runnable() {
|
||||
//
|
||||
// @Override
|
||||
// public void run()
|
||||
// {
|
||||
// w.getPlayer().walk(5, 5);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// w.getPlayer().setMoveListener(new Runnable() {
|
||||
//
|
||||
// @Override
|
||||
// public void run()
|
||||
// {
|
||||
// if (InputSystem.isKeyDown(Keys.LEFT)) {
|
||||
// w.getPlayer().walk(-1, 0);
|
||||
// } else if (InputSystem.isKeyDown(Keys.RIGHT)) {
|
||||
// w.getPlayer().walk(1, 0);
|
||||
// } else if (InputSystem.isKeyDown(Keys.UP)) {
|
||||
// w.getPlayer().walk(0, -1);
|
||||
// } else if (InputSystem.isKeyDown(Keys.DOWN)) {
|
||||
// w.getPlayer().walk(0, 1);
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ public class LayerFlyingCat extends ScreenLayer implements MouseButtonEvent.List
|
||||
{
|
||||
if (!event.isDown()) return;
|
||||
|
||||
cat_position.setTo(event.getPos());
|
||||
cat_position.animate(event.getPos());
|
||||
|
||||
final double newSize = root.height().perc(10 + rand.nextInt(40)).value();
|
||||
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
package mightypork.rogue.world;
|
||||
|
||||
|
||||
import mightypork.rogue.world.map.Level;
|
||||
import mightypork.rogue.world.map.TileRenderContext;
|
||||
import mightypork.util.constraints.rect.Rect;
|
||||
import mightypork.util.constraints.rect.RectConst;
|
||||
import mightypork.util.constraints.rect.proxy.RectBound;
|
||||
import mightypork.util.constraints.vect.VectConst;
|
||||
import mightypork.util.control.timing.Updateable;
|
||||
|
||||
|
||||
public class ClientWorld implements Updateable, WorldAccess {
|
||||
|
||||
private Level level = null;
|
||||
|
||||
private final PlayerEntity player = null;
|
||||
|
||||
|
||||
@Override
|
||||
public void update(double delta)
|
||||
{
|
||||
player.update(delta);
|
||||
|
||||
level.updateVisual(player, delta);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draw on screen
|
||||
*
|
||||
* @param viewport rendering area on screen
|
||||
* @param xTiles Desired nr of tiles horizontally
|
||||
* @param yTiles Desired nr of tiles vertically
|
||||
* @param minSize minimum tile size
|
||||
*/
|
||||
public void render(final RectBound viewport, final int yTiles, final int xTiles, final int minSize)
|
||||
{
|
||||
final Rect r = viewport.getRect();
|
||||
final double vpH = r.height().value();
|
||||
final double vpW = r.width().value();
|
||||
|
||||
// adjust tile size to fit desired amount of tiles
|
||||
|
||||
final double allowedSizeW = vpW / xTiles;
|
||||
final double allowedSizeH = vpH / yTiles;
|
||||
int tileSize = (int) Math.round(Math.max(Math.min(allowedSizeH, allowedSizeW), minSize));
|
||||
|
||||
tileSize -= tileSize % 16;
|
||||
|
||||
final VectConst vpCenter = r.center().sub(tileSize * 0.5, tileSize).freeze(); // 0.5 to center, 1 to move up (down is teh navbar)
|
||||
|
||||
final double playerX = player.getPosition().getVisualX();
|
||||
final double playerY = player.getPosition().getVisualY();
|
||||
|
||||
// total map area
|
||||
//@formatter:off
|
||||
final RectConst mapRect = vpCenter.startRect().grow(
|
||||
playerX*tileSize,
|
||||
(level.getWidth() - playerX) * tileSize,
|
||||
playerY*tileSize,
|
||||
(level.getHeight() - playerY) * tileSize
|
||||
).freeze();
|
||||
//@formatter:on
|
||||
|
||||
// tiles to render
|
||||
final int x1 = (int) Math.floor(playerX - (vpW / tileSize));
|
||||
final int y1 = (int) Math.floor(playerY - (vpH / tileSize));
|
||||
final int x2 = (int) Math.ceil(playerX + (vpW / tileSize));
|
||||
final int y2 = (int) Math.ceil(playerY + (vpH / tileSize));
|
||||
|
||||
final TileRenderContext trc = new TileRenderContext(level, mapRect); //-tileSize*0.5
|
||||
for (trc.y = y1; trc.y <= y2; trc.y++) {
|
||||
for (trc.x = x1; trc.x <= x2; trc.x++) {
|
||||
trc.render();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public PlayerEntity getPlayer()
|
||||
{
|
||||
return player;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isServer()
|
||||
{
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
package mightypork.rogue.world;
|
||||
|
||||
import mightypork.rogue.world.map.Level;
|
||||
import mightypork.util.control.timing.Updateable;
|
||||
|
||||
|
||||
/**
|
||||
* Abstraction of client-server connection from the client's view
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public abstract class ClientWorldAccess implements Updateable {
|
||||
|
||||
public abstract Level getLevel();
|
||||
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
package mightypork.rogue.world;
|
||||
|
||||
|
||||
import mightypork.rogue.world.map.Level;
|
||||
import mightypork.rogue.world.map.TileRenderContext;
|
||||
import mightypork.util.constraints.rect.Rect;
|
||||
import mightypork.util.constraints.rect.RectConst;
|
||||
import mightypork.util.constraints.rect.proxy.RectBound;
|
||||
import mightypork.util.constraints.vect.VectConst;
|
||||
|
||||
|
||||
public class LevelRenderer {
|
||||
|
||||
/**
|
||||
* Draw on screen
|
||||
*
|
||||
* @param viewport rendering area on screen
|
||||
* @param xTiles Desired nr of tiles horizontally
|
||||
* @param yTiles Desired nr of tiles vertically
|
||||
* @param minSize minimum tile size
|
||||
*/
|
||||
public static void render(Level level, PlayerEntity player, RectBound viewport, final int yTiles, final int xTiles, final int minSize)
|
||||
{
|
||||
final Rect r = viewport.getRect();
|
||||
final double vpH = r.height().value();
|
||||
final double vpW = r.width().value();
|
||||
|
||||
// adjust tile size to fit desired amount of tiles
|
||||
|
||||
final double allowedSizeW = vpW / xTiles;
|
||||
final double allowedSizeH = vpH / yTiles;
|
||||
int tileSize = (int) Math.round(Math.max(Math.min(allowedSizeH, allowedSizeW), minSize));
|
||||
|
||||
tileSize -= tileSize % 16;
|
||||
|
||||
final VectConst vpCenter = r.center().sub(tileSize * 0.5, tileSize).freeze(); // 0.5 to center, 1 to move up (down is teh navbar)
|
||||
|
||||
final double playerX = player.getPosition().getVisualX();
|
||||
final double playerY = player.getPosition().getVisualY();
|
||||
|
||||
// total map area
|
||||
//@formatter:off
|
||||
final RectConst mapRect = vpCenter.startRect().grow(
|
||||
playerX*tileSize,
|
||||
(level.getWidth() - playerX) * tileSize,
|
||||
playerY*tileSize,
|
||||
(level.getHeight() - playerY) * tileSize
|
||||
).freeze();
|
||||
//@formatter:on
|
||||
|
||||
// tiles to render
|
||||
final int x1 = (int) Math.floor(playerX - (vpW / tileSize));
|
||||
final int y1 = (int) Math.floor(playerY - (vpH / tileSize));
|
||||
final int x2 = (int) Math.ceil(playerX + (vpW / tileSize));
|
||||
final int y2 = (int) Math.ceil(playerY + (vpH / tileSize));
|
||||
|
||||
final TileRenderContext trc = new TileRenderContext(level, mapRect); //-tileSize*0.5
|
||||
for (trc.y = y1; trc.y <= y2; trc.y++) {
|
||||
for (trc.x = x1; trc.x <= x2; trc.x++) {
|
||||
trc.render();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,9 +3,9 @@ package mightypork.rogue.world;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import mightypork.rogue.world.map.Level;
|
||||
import mightypork.rogue.world.tile.TileModel;
|
||||
import mightypork.rogue.world.level.Level;
|
||||
import mightypork.rogue.world.tile.Tiles;
|
||||
import mightypork.rogue.world.tile.models.TileModel;
|
||||
|
||||
|
||||
public class MapGenerator {
|
||||
@@ -13,19 +13,19 @@ public class MapGenerator {
|
||||
public static final Random rand = new Random();
|
||||
|
||||
|
||||
public static ServerWorld createWorld(long seed)
|
||||
public static World createWorld(long seed)
|
||||
{
|
||||
synchronized (rand) {
|
||||
rand.setSeed(seed);
|
||||
|
||||
final ServerWorld w = new ServerWorld();
|
||||
final World w = new World();
|
||||
w.setSeed(seed);
|
||||
|
||||
w.addLevel(createLevel(rand.nextLong(), Tiles.CRYSTAL_FLOOR, Tiles.CRYSTAL_WALL));
|
||||
w.addLevel(createLevel(rand.nextLong(), Tiles.BRCOBBLE_FLOOR, Tiles.BRCOBBLE_WALL));
|
||||
|
||||
// TODO place on start position
|
||||
w.addPlayer("local", new PlayerEntity(10, 10, 0));
|
||||
w.createPlayer(10, 10, 0);
|
||||
return w;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,8 @@ public class PathStep implements IonBinary {
|
||||
public int y;
|
||||
|
||||
|
||||
public PathStep(int x, int y) {
|
||||
public PathStep(int x, int y)
|
||||
{
|
||||
this.x = x < 1 ? -1 : x > 0 ? 1 : 0;
|
||||
this.y = y < 1 ? -1 : y > 0 ? 1 : 0;
|
||||
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
package mightypork.rogue.world;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import mightypork.rogue.world.map.MapObserver;
|
||||
import mightypork.util.ion.IonBundle;
|
||||
|
||||
|
||||
/**
|
||||
* Player info
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public class PlayerEntity extends WorldEntity implements MapObserver {
|
||||
|
||||
public static final double PLAYER_STEP_TIME = 0.3;
|
||||
|
||||
public boolean connected = false;
|
||||
|
||||
|
||||
public PlayerEntity() {
|
||||
super();
|
||||
}
|
||||
|
||||
|
||||
public PlayerEntity(ServerWorld world, int x, int y, int floor) {
|
||||
super(world, new WorldPos(x, y, floor));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void load(IonBundle bundle) throws IOException
|
||||
{
|
||||
super.load(bundle);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void save(IonBundle bundle) throws IOException
|
||||
{
|
||||
super.save(bundle);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getViewRange()
|
||||
{
|
||||
return 15;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected double getStepTime()
|
||||
{
|
||||
return PLAYER_STEP_TIME;
|
||||
}
|
||||
|
||||
|
||||
public boolean isConnected()
|
||||
{
|
||||
return connected;
|
||||
}
|
||||
|
||||
|
||||
public void setConnected(boolean connected)
|
||||
{
|
||||
this.connected = connected;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public WorldPos getViewPosition()
|
||||
{
|
||||
return getPosition();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPhysical()
|
||||
{
|
||||
return isConnected();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package mightypork.rogue.world;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import mightypork.util.ion.IonBundle;
|
||||
import mightypork.util.ion.IonBundled;
|
||||
|
||||
|
||||
public class PlayerInfo implements IonBundled {
|
||||
|
||||
private int eid = -1; // marks not initialized
|
||||
private int level;
|
||||
|
||||
|
||||
@Override
|
||||
public void load(IonBundle bundle) throws IOException
|
||||
{
|
||||
eid = bundle.get("attached_eid", 0);
|
||||
level = bundle.get("current_level", 0);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void save(IonBundle bundle) throws IOException
|
||||
{
|
||||
bundle.put("attached_eid", eid);
|
||||
bundle.put("current_level", level);
|
||||
}
|
||||
|
||||
|
||||
public void setEID(int eid)
|
||||
{
|
||||
if (isInitialized()) throw new RuntimeException("Cannot change player EID.");
|
||||
this.eid = eid;
|
||||
}
|
||||
|
||||
|
||||
public void setLevel(int level)
|
||||
{
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
|
||||
public int getEID()
|
||||
{
|
||||
return eid;
|
||||
}
|
||||
|
||||
|
||||
public int getLevel()
|
||||
{
|
||||
return level;
|
||||
}
|
||||
|
||||
|
||||
public boolean isInitialized()
|
||||
{
|
||||
return eid != -1;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
package mightypork.rogue.world;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
|
||||
import mightypork.rogue.world.map.Level;
|
||||
import mightypork.util.control.timing.Updateable;
|
||||
import mightypork.util.ion.IonBundle;
|
||||
import mightypork.util.ion.IonBundled;
|
||||
|
||||
|
||||
/**
|
||||
* World on a server. To a server, all players and levels are equal.
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public class ServerWorld implements IonBundled, Updateable, WorldAccess {
|
||||
|
||||
private final ArrayList<Level> levels = new ArrayList<>();
|
||||
|
||||
private final Map<String, PlayerEntity> players = new HashMap<>();
|
||||
|
||||
/** This seed can be used to re-create identical world. */
|
||||
private long seed;
|
||||
|
||||
/** Next spawned entity ID */
|
||||
private long eid;
|
||||
|
||||
|
||||
@Override
|
||||
public void load(IonBundle in) throws IOException
|
||||
{
|
||||
seed = in.get("seed", 0L);
|
||||
eid = in.get("eid", 0L);
|
||||
in.loadSequence("levels", levels);
|
||||
in.loadMap("players", players);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void save(IonBundle out) throws IOException
|
||||
{
|
||||
out.put("seed", seed);
|
||||
out.put("eid", eid);
|
||||
out.putSequence("levels", levels);
|
||||
out.putMap("players", players);
|
||||
}
|
||||
|
||||
|
||||
public void addLevel(Level level)
|
||||
{
|
||||
levels.add(level);
|
||||
}
|
||||
|
||||
public void addPlayer(String name, PlayerEntity player)
|
||||
{
|
||||
players.put(name, player);
|
||||
}
|
||||
|
||||
public void removePlayer(String name)
|
||||
{
|
||||
players.remove(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void update(double delta)
|
||||
{
|
||||
Set<Integer> occupiedLevels = new HashSet<>();
|
||||
|
||||
// food meters and such
|
||||
for (final PlayerEntity pl : players.values()) {
|
||||
if(pl.isConnected()) {
|
||||
pl.updateLogic(this, delta);
|
||||
occupiedLevels.add(pl.getPosition().floor);
|
||||
}
|
||||
}
|
||||
|
||||
for(int i : occupiedLevels) {
|
||||
levels.get(i).updateLogic(this, delta);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void setSeed(long seed)
|
||||
{
|
||||
this.seed = seed;
|
||||
}
|
||||
|
||||
|
||||
public long getSeed()
|
||||
{
|
||||
return seed;
|
||||
}
|
||||
|
||||
|
||||
public long generateEntityId()
|
||||
{
|
||||
return eid++;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isServer()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
package mightypork.rogue.world;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import mightypork.rogue.world.entity.Entities;
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.level.Level;
|
||||
import mightypork.util.constraints.rect.proxy.RectBound;
|
||||
import mightypork.util.control.timing.Updateable;
|
||||
import mightypork.util.ion.IonBundle;
|
||||
import mightypork.util.ion.IonBundled;
|
||||
|
||||
|
||||
/**
|
||||
* World on a server. To a server, all players and levels are equal.
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public class World implements IonBundled, Updateable {
|
||||
|
||||
private final ArrayList<Level> levels = new ArrayList<>();
|
||||
|
||||
private final PlayerInfo player = new PlayerInfo();
|
||||
|
||||
private long seed; // world seed
|
||||
private int eid; // next entity ID
|
||||
|
||||
|
||||
@Override
|
||||
public void load(IonBundle in) throws IOException
|
||||
{
|
||||
seed = in.get("seed", 0L);
|
||||
eid = in.get("next_eid", 0);
|
||||
in.loadSequence("levels", levels);
|
||||
in.loadBundled("player", player);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void save(IonBundle out) throws IOException
|
||||
{
|
||||
out.put("seed", seed);
|
||||
out.put("next_eid", eid);
|
||||
out.putSequence("levels", levels);
|
||||
out.putBundled("player", player);
|
||||
}
|
||||
|
||||
|
||||
public void addLevel(Level level)
|
||||
{
|
||||
levels.add(level);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void update(double delta)
|
||||
{
|
||||
getCurrentLevel().update(delta);
|
||||
}
|
||||
|
||||
|
||||
public void setSeed(long seed)
|
||||
{
|
||||
this.seed = seed;
|
||||
}
|
||||
|
||||
|
||||
public long getSeed()
|
||||
{
|
||||
return seed;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return new entity ID
|
||||
*/
|
||||
public int getNewEID()
|
||||
{
|
||||
return eid++;
|
||||
}
|
||||
|
||||
|
||||
public void createPlayer(int x, int y, int level)
|
||||
{
|
||||
if (player.isInitialized()) {
|
||||
throw new RuntimeException("Player already created.");
|
||||
}
|
||||
|
||||
// make entity
|
||||
int playerEid = getNewEID();
|
||||
|
||||
final Entity entity = Entities.PLAYER.createEntity(playerEid, new WorldPos(x, y));
|
||||
|
||||
player.setLevel(level);
|
||||
player.setEID(playerEid);
|
||||
|
||||
levels.get(level).addEntity(entity);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draw on screen
|
||||
*
|
||||
* @param viewport rendering area on screen
|
||||
* @param xTiles Desired nr of tiles horizontally
|
||||
* @param yTiles Desired nr of tiles vertically
|
||||
* @param minSize minimum tile size
|
||||
*/
|
||||
public void render(RectBound viewport, final int yTiles, final int xTiles, final int minSize)
|
||||
{
|
||||
getCurrentLevel().render(player, viewport, yTiles, xTiles, minSize);
|
||||
}
|
||||
|
||||
|
||||
public Level getCurrentLevel()
|
||||
{
|
||||
return levels.get(player.getLevel());
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package mightypork.rogue.world;
|
||||
|
||||
|
||||
public interface WorldAccess {
|
||||
|
||||
public boolean isServer();
|
||||
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
package mightypork.rogue.world;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
|
||||
import mightypork.util.ion.IonBundle;
|
||||
import mightypork.util.ion.IonBundled;
|
||||
|
||||
|
||||
public abstract class WorldEntity implements IonBundled {
|
||||
|
||||
private final WorldPos position = new WorldPos();
|
||||
private Runnable moveEndListener, pathEndListener;
|
||||
|
||||
private long serial_id = 0L;
|
||||
|
||||
private final Queue<PathStep> path = new LinkedList<>();
|
||||
|
||||
|
||||
public WorldEntity(ServerWorld world, WorldPos pos) {
|
||||
this.serial_id = world.generateEntityId();
|
||||
this.position.setTo(pos);
|
||||
}
|
||||
|
||||
|
||||
public WorldEntity() {
|
||||
// for ion
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void save(IonBundle bundle) throws IOException
|
||||
{
|
||||
bundle.putBundled("pos", position);
|
||||
bundle.putSequence("steps", path);
|
||||
bundle.put("eid", serial_id);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void load(IonBundle bundle) throws IOException
|
||||
{
|
||||
bundle.loadBundled("pos", position);
|
||||
bundle.loadSequence("path", path);
|
||||
serial_id = bundle.get("eid", 0L);
|
||||
}
|
||||
|
||||
|
||||
public void setMoveEndListener(Runnable moveEndListener)
|
||||
{
|
||||
this.moveEndListener = moveEndListener;
|
||||
}
|
||||
|
||||
|
||||
public void setPathEndListener(Runnable pathEndListener)
|
||||
{
|
||||
this.pathEndListener = pathEndListener;
|
||||
}
|
||||
|
||||
|
||||
public WorldPos getPosition()
|
||||
{
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
public void setPosition(WorldPos pos)
|
||||
{
|
||||
position.setTo(pos);
|
||||
}
|
||||
|
||||
|
||||
public void setPosition(int x, int y, int floor)
|
||||
{
|
||||
position.setTo(x, y, floor);
|
||||
cancelPath(); // discard remaining steps
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param world the world
|
||||
* @param delta delta time
|
||||
*/
|
||||
public void updateLogic(WorldAccess world, double delta)
|
||||
{
|
||||
if(!isPhysical()) return;
|
||||
|
||||
if (!position.isFinished()) {
|
||||
position.update(delta);
|
||||
}
|
||||
|
||||
if (position.isFinished()) {
|
||||
|
||||
if (moveEndListener != null) moveEndListener.run();
|
||||
|
||||
if (!path.isEmpty()) {
|
||||
// get next step to walk
|
||||
PathStep step = path.poll();
|
||||
position.walk(step.x, step.y, getStepTime());
|
||||
} else {
|
||||
// notify AI or whatever
|
||||
if (pathEndListener != null) pathEndListener.run();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param world the world
|
||||
* @param delta delta time
|
||||
*/
|
||||
public void updateVisual(WorldAccess world, double delta)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public boolean isPathFinished()
|
||||
{
|
||||
return position.isFinished() && path.isEmpty();
|
||||
}
|
||||
|
||||
|
||||
public void addStep(PathStep step)
|
||||
{
|
||||
path.add(step);
|
||||
}
|
||||
|
||||
|
||||
public void cancelPath()
|
||||
{
|
||||
path.clear();
|
||||
}
|
||||
|
||||
|
||||
protected abstract double getStepTime();
|
||||
|
||||
public boolean isPhysical() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,19 +18,20 @@ import mightypork.util.math.Easing;
|
||||
*/
|
||||
public class WorldPos implements IonBundled, Updateable {
|
||||
|
||||
public int x, y, floor;
|
||||
public int x, y;
|
||||
private final VectAnimated walkOffset = new VectAnimated(Vect.ZERO, Easing.LINEAR);
|
||||
|
||||
|
||||
public WorldPos(int x, int y, int floor) {
|
||||
public WorldPos(int x, int y)
|
||||
{
|
||||
super();
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.floor = floor;
|
||||
}
|
||||
|
||||
|
||||
public WorldPos() {
|
||||
public WorldPos()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +46,6 @@ public class WorldPos implements IonBundled, Updateable {
|
||||
{
|
||||
x = in.get("x", 0);
|
||||
y = in.get("y", 0);
|
||||
floor = in.get("z", 0);
|
||||
walkOffset.reset();
|
||||
}
|
||||
|
||||
@@ -55,7 +55,6 @@ public class WorldPos implements IonBundled, Updateable {
|
||||
{
|
||||
out.put("x", x);
|
||||
out.put("y", y);
|
||||
out.put("z", floor);
|
||||
}
|
||||
|
||||
|
||||
@@ -71,12 +70,6 @@ public class WorldPos implements IonBundled, Updateable {
|
||||
}
|
||||
|
||||
|
||||
public double getFloor()
|
||||
{
|
||||
return floor;
|
||||
}
|
||||
|
||||
|
||||
public double getVisualX()
|
||||
{
|
||||
return x + walkOffset.x();
|
||||
@@ -97,18 +90,9 @@ public class WorldPos implements IonBundled, Updateable {
|
||||
}
|
||||
|
||||
|
||||
public void setTo(int x, int y, int floor)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.floor = floor;
|
||||
walkOffset.reset();
|
||||
}
|
||||
|
||||
|
||||
public void setTo(WorldPos other)
|
||||
{
|
||||
setTo(other.x, other.y, other.floor);
|
||||
setTo(other.x, other.y);
|
||||
}
|
||||
|
||||
|
||||
@@ -117,7 +101,6 @@ public class WorldPos implements IonBundled, Updateable {
|
||||
{
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + floor;
|
||||
result = prime * result + x;
|
||||
result = prime * result + y;
|
||||
return result;
|
||||
@@ -131,7 +114,6 @@ public class WorldPos implements IonBundled, Updateable {
|
||||
if (obj == null) return false;
|
||||
if (!(obj instanceof WorldPos)) return false;
|
||||
final WorldPos other = (WorldPos) obj;
|
||||
if (floor != other.floor) return false;
|
||||
if (x != other.x) return false;
|
||||
if (y != other.y) return false;
|
||||
return true;
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package mightypork.rogue.world.entity;
|
||||
|
||||
|
||||
import mightypork.rogue.world.entity.models.EntityModel;
|
||||
import mightypork.rogue.world.entity.models.PlayerModel;
|
||||
|
||||
|
||||
/**
|
||||
* Tile registry
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public final class Entities {
|
||||
|
||||
private static final EntityModel[] entities = new EntityModel[256];
|
||||
|
||||
public static final EntityModel PLAYER = new PlayerModel(0);
|
||||
|
||||
|
||||
public static void register(int id, EntityModel model)
|
||||
{
|
||||
if (id < 0 || id >= entities.length) {
|
||||
throw new IllegalArgumentException("Entity model ID " + id + " is out of range.");
|
||||
}
|
||||
|
||||
if (entities[id] != null) {
|
||||
throw new IllegalArgumentException("Entity model ID " + id + " already in use.");
|
||||
}
|
||||
|
||||
entities[id] = model;
|
||||
}
|
||||
|
||||
|
||||
public static EntityModel get(int id)
|
||||
{
|
||||
final EntityModel e = entities[id];
|
||||
|
||||
if (e == null) {
|
||||
throw new IllegalArgumentException("No entity model with ID " + id + ".");
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
package mightypork.rogue.world.entity;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Queue;
|
||||
|
||||
import mightypork.rogue.world.PathStep;
|
||||
import mightypork.rogue.world.World;
|
||||
import mightypork.rogue.world.WorldPos;
|
||||
import mightypork.rogue.world.entity.models.EntityModel;
|
||||
import mightypork.rogue.world.level.Level;
|
||||
import mightypork.util.ion.IonBinary;
|
||||
import mightypork.util.ion.IonBundle;
|
||||
import mightypork.util.ion.IonBundled;
|
||||
import mightypork.util.ion.IonInput;
|
||||
import mightypork.util.ion.IonOutput;
|
||||
|
||||
|
||||
/**
|
||||
* World entity (mob or player)
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public final class Entity implements IonBinary, IonBundled {
|
||||
|
||||
// binary & bundled - binary stores via a bundle
|
||||
|
||||
public static final int ION_MARK = 52;
|
||||
|
||||
private final WorldPos position = new WorldPos();
|
||||
|
||||
/** Entity ID */
|
||||
private int eid = 0;
|
||||
|
||||
/** Model ID */
|
||||
private int id;
|
||||
|
||||
private final Queue<PathStep> path = new LinkedList<>();
|
||||
private EntityModel model;
|
||||
private final IonBundle metadata = new IonBundle();
|
||||
|
||||
|
||||
public Entity(int eid, WorldPos pos, EntityModel entityModel)
|
||||
{
|
||||
this.eid = eid;
|
||||
this.position.setTo(pos);
|
||||
|
||||
setModel(entityModel);
|
||||
}
|
||||
|
||||
|
||||
private void setModel(EntityModel entityModel)
|
||||
{
|
||||
this.id = entityModel.id;
|
||||
this.model = entityModel;
|
||||
}
|
||||
|
||||
|
||||
public Entity()
|
||||
{
|
||||
// for ion
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public short getIonMark()
|
||||
{
|
||||
return ION_MARK;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void save(IonOutput out) throws IOException
|
||||
{
|
||||
final IonBundle ib = new IonBundle();
|
||||
save(ib);
|
||||
out.writeBundle(ib);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void load(IonInput in) throws IOException
|
||||
{
|
||||
load(in.readBundle());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void save(IonBundle bundle) throws IOException
|
||||
{
|
||||
bundle.put("id", id);
|
||||
bundle.putBundled("pos", position);
|
||||
bundle.putSequence("steps", path);
|
||||
bundle.put("eid", eid);
|
||||
bundle.put("metadata", metadata);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void load(IonBundle bundle) throws IOException
|
||||
{
|
||||
id = bundle.get("id", 0);
|
||||
|
||||
if (model == null || id != model.id) {
|
||||
setModel(Entities.get(id));
|
||||
}
|
||||
|
||||
bundle.loadBundled("pos", position);
|
||||
bundle.loadSequence("path", path);
|
||||
eid = bundle.get("eid", eid);
|
||||
|
||||
metadata.clear();
|
||||
bundle.loadBundle("metadata", metadata);
|
||||
}
|
||||
|
||||
|
||||
public int getEID()
|
||||
{
|
||||
return eid;
|
||||
}
|
||||
|
||||
|
||||
public WorldPos getPosition()
|
||||
{
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
public void setPosition(WorldPos pos)
|
||||
{
|
||||
position.setTo(pos);
|
||||
}
|
||||
|
||||
|
||||
public void setPosition(int x, int y)
|
||||
{
|
||||
position.setTo(x, y);
|
||||
cancelPath(); // discard remaining steps
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param world the world
|
||||
* @param delta delta time
|
||||
*/
|
||||
public void update(World world, Level level, double delta)
|
||||
{
|
||||
if (!position.isFinished()) {
|
||||
position.update(delta);
|
||||
}
|
||||
|
||||
if (position.isFinished()) {
|
||||
|
||||
model.onStepFinished(this, world, level);
|
||||
|
||||
if (!path.isEmpty()) {
|
||||
// get next step to walk
|
||||
final PathStep step = path.poll();
|
||||
position.walk(step.x, step.y, getStepTime());
|
||||
} else {
|
||||
// notify AI or whatever
|
||||
model.onPathFinished(this, world, level);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean isPathFinished()
|
||||
{
|
||||
return position.isFinished() && path.isEmpty();
|
||||
}
|
||||
|
||||
|
||||
public void addStep(PathStep step)
|
||||
{
|
||||
path.add(step);
|
||||
}
|
||||
|
||||
|
||||
public void cancelPath()
|
||||
{
|
||||
path.clear();
|
||||
}
|
||||
|
||||
|
||||
protected double getStepTime()
|
||||
{
|
||||
return model.getStepTime(this);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package mightypork.rogue.world.entity.models;
|
||||
|
||||
|
||||
import mightypork.rogue.world.World;
|
||||
import mightypork.rogue.world.WorldPos;
|
||||
import mightypork.rogue.world.entity.Entities;
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.entity.renderers.EntityRenderer;
|
||||
import mightypork.rogue.world.level.Level;
|
||||
|
||||
|
||||
/**
|
||||
* Entity model
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public abstract class EntityModel {
|
||||
|
||||
/** Model ID */
|
||||
public final int id;
|
||||
public EntityRenderer renderer = EntityRenderer.NONE;
|
||||
|
||||
|
||||
public EntityModel(int id)
|
||||
{
|
||||
Entities.register(id, this);
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
|
||||
public EntityModel setRenderer(EntityRenderer renderer)
|
||||
{
|
||||
this.renderer = renderer;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return new tile of this type; if 100% invariant, can return cached one.
|
||||
*/
|
||||
public Entity createEntity(int eid, WorldPos pos)
|
||||
{
|
||||
return new Entity(eid, pos, this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update entity
|
||||
*/
|
||||
public abstract void update(Entity entity, Level level, double delta);
|
||||
|
||||
|
||||
/**
|
||||
* @return true if this entity type has metadata worth saving
|
||||
*/
|
||||
public abstract boolean hasMetadata();
|
||||
|
||||
|
||||
/**
|
||||
* @param entity the value is valid for
|
||||
* @return step time (seconds)
|
||||
*/
|
||||
public abstract double getStepTime(Entity entity);
|
||||
|
||||
|
||||
public abstract void onStepFinished(Entity entity, World world, Level level);
|
||||
|
||||
|
||||
public abstract void onPathFinished(Entity entity, World world, Level level);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package mightypork.rogue.world.entity.models;
|
||||
|
||||
|
||||
import mightypork.rogue.world.World;
|
||||
import mightypork.rogue.world.WorldPos;
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.level.Level;
|
||||
|
||||
|
||||
/**
|
||||
* Player info
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public class PlayerModel extends EntityModel {
|
||||
|
||||
private static final double STEP_TIME = 0.3;
|
||||
|
||||
|
||||
public PlayerModel(int id)
|
||||
{
|
||||
super(id);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Entity createEntity(int eid, WorldPos pos)
|
||||
{
|
||||
final Entity e = super.createEntity(eid, pos);
|
||||
|
||||
// set metadata
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void update(Entity entity, Level level, double delta)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasMetadata()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public double getStepTime(Entity entity)
|
||||
{
|
||||
return STEP_TIME;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onStepFinished(Entity entity, World world, Level level)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onPathFinished(Entity entity, World world, Level level)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
package mightypork.rogue.world.entity.renderers;
|
||||
|
||||
|
||||
public class EntityRenderer {
|
||||
|
||||
public static final EntityRenderer NONE = new NullEntityRenderer();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package mightypork.rogue.world.entity.renderers;
|
||||
|
||||
|
||||
public class NullEntityRenderer extends EntityRenderer {
|
||||
|
||||
}
|
||||
@@ -13,7 +13,7 @@ public class Item implements IonBinary {
|
||||
|
||||
public static final short ION_MARK = 51;
|
||||
|
||||
private transient ItemModel model;
|
||||
private ItemModel model;
|
||||
|
||||
public int id;
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ public final class Items {
|
||||
private static final ItemModel[] items = new ItemModel[256];
|
||||
|
||||
|
||||
static void register(int id, ItemModel model)
|
||||
public static void register(int id, ItemModel model)
|
||||
{
|
||||
if (id < 0 || id >= items.length) if (items[id] != null) throw new IllegalArgumentException("Item ID " + id + " already in use.");
|
||||
|
||||
|
||||
@@ -0,0 +1,330 @@
|
||||
package mightypork.rogue.world.level;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import mightypork.gamecore.render.Render;
|
||||
import mightypork.rogue.Res;
|
||||
import mightypork.rogue.world.PlayerInfo;
|
||||
import mightypork.rogue.world.WorldPos;
|
||||
import mightypork.rogue.world.entity.Entity;
|
||||
import mightypork.rogue.world.level.render.TileRenderContext;
|
||||
import mightypork.rogue.world.tile.Tile;
|
||||
import mightypork.rogue.world.tile.Tiles;
|
||||
import mightypork.rogue.world.tile.models.TileModel;
|
||||
import mightypork.util.constraints.rect.Rect;
|
||||
import mightypork.util.constraints.rect.RectConst;
|
||||
import mightypork.util.constraints.rect.proxy.RectBound;
|
||||
import mightypork.util.constraints.vect.VectConst;
|
||||
import mightypork.util.ion.IonBinary;
|
||||
import mightypork.util.ion.IonBundle;
|
||||
import mightypork.util.ion.IonInput;
|
||||
import mightypork.util.ion.IonOutput;
|
||||
import mightypork.util.math.noise.NoiseGen;
|
||||
|
||||
|
||||
/**
|
||||
* One level of the dungeon
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public class Level implements MapAccess, IonBinary {
|
||||
|
||||
public static final int ION_MARK = 53;
|
||||
|
||||
private static final boolean USE_BATCH_RENDERING = true;
|
||||
|
||||
private int width, height;
|
||||
|
||||
/** Array of tiles [y][x] */
|
||||
private Tile[][] tiles;
|
||||
|
||||
private final Map<Integer, Entity> entity_map = new HashMap<>();
|
||||
private final Set<Entity> entity_set = new HashSet<>();
|
||||
|
||||
/** Level seed (used for generation and tile variation) */
|
||||
public long seed;
|
||||
|
||||
private transient NoiseGen noiseGen;
|
||||
|
||||
|
||||
public Level()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public Level(int width, int height)
|
||||
{
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
buildArray();
|
||||
}
|
||||
|
||||
|
||||
private void buildArray()
|
||||
{
|
||||
this.tiles = new Tile[height][width];
|
||||
}
|
||||
|
||||
|
||||
public void fill(short id)
|
||||
{
|
||||
fill(Tiles.get(id));
|
||||
}
|
||||
|
||||
|
||||
public void fill(TileModel model)
|
||||
{
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
tiles[y][x] = model.createTile();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final Tile getTile(int x, int y)
|
||||
{
|
||||
if (x < 0 || x >= width || y < 0 || y >= height) return Tiles.NULL_SOLID.createTile(); // out of range
|
||||
|
||||
return tiles[y][x];
|
||||
}
|
||||
|
||||
|
||||
public final void setTile(TileModel model, int x, int y)
|
||||
{
|
||||
setTile(model.createTile(), x, y);
|
||||
}
|
||||
|
||||
|
||||
public final void setTile(int tileId, int x, int y)
|
||||
{
|
||||
setTile(new Tile(tileId), x, y);
|
||||
}
|
||||
|
||||
|
||||
public final void setTile(Tile tile, int x, int y)
|
||||
{
|
||||
if (x < 0 || x > width || y < 0 || y >= height) return; // out of range
|
||||
|
||||
tiles[y][x] = tile;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final int getWidth()
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final int getHeight()
|
||||
{
|
||||
return height;
|
||||
}
|
||||
|
||||
|
||||
public void setSeed(long seed)
|
||||
{
|
||||
this.seed = seed;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long getSeed()
|
||||
{
|
||||
return seed;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void load(IonInput in) throws IOException
|
||||
{
|
||||
// metadata
|
||||
final IonBundle ib = in.readBundle();
|
||||
seed = ib.get("seed", 0L);
|
||||
width = ib.get("w", 0);
|
||||
height = ib.get("h", 0);
|
||||
|
||||
ib.loadSequence("entities", entity_set);
|
||||
for (final Entity ent : entity_set) {
|
||||
entity_map.put(ent.getEID(), ent);
|
||||
}
|
||||
|
||||
// init array of size
|
||||
buildArray();
|
||||
|
||||
// load tiles
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
// no mark
|
||||
tiles[y][x] = new Tile();
|
||||
tiles[y][x].load(in);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void save(IonOutput out) throws IOException
|
||||
{
|
||||
// metadata
|
||||
final IonBundle ib = new IonBundle();
|
||||
ib.put("seed", seed);
|
||||
ib.put("w", width);
|
||||
ib.put("h", height);
|
||||
ib.putSequence("entities", entity_set);
|
||||
out.writeBundle(ib);
|
||||
|
||||
// tiles (writing this way to save space)
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
// no mark to save space
|
||||
tiles[y][x].save(out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public short getIonMark()
|
||||
{
|
||||
return ION_MARK;
|
||||
}
|
||||
|
||||
|
||||
public void update(double delta)
|
||||
{
|
||||
// just update them all
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
getTile(x, y).update(this, delta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public NoiseGen getNoiseGen()
|
||||
{
|
||||
if (noiseGen == null) {
|
||||
noiseGen = new NoiseGen(0.2, 0, 0.5, 1, seed);
|
||||
}
|
||||
|
||||
return noiseGen;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Draw on screen
|
||||
*
|
||||
* @param playerInfo layer
|
||||
* @param viewport rendering area on screen
|
||||
* @param xTiles Desired nr of tiles horizontally
|
||||
* @param yTiles Desired nr of tiles vertically
|
||||
* @param minSize minimum tile size
|
||||
*/
|
||||
public void render(PlayerInfo playerInfo, RectBound viewport, final int yTiles, final int xTiles, final int minSize)
|
||||
{
|
||||
final WorldPos pos;
|
||||
|
||||
try {
|
||||
pos = getEntity(playerInfo.getEID()).getPosition();
|
||||
} catch (NullPointerException e) {
|
||||
throw new RuntimeException("Player entity not found in level.", e);
|
||||
}
|
||||
|
||||
final Rect r = viewport.getRect();
|
||||
final double vpH = r.height().value();
|
||||
final double vpW = r.width().value();
|
||||
|
||||
// adjust tile size to fit desired amount of tiles
|
||||
|
||||
final double allowedSizeW = vpW / xTiles;
|
||||
final double allowedSizeH = vpH / yTiles;
|
||||
int tileSize = (int) Math.round(Math.max(Math.min(allowedSizeH, allowedSizeW), minSize));
|
||||
|
||||
tileSize -= tileSize % 16;
|
||||
|
||||
final VectConst vpCenter = r.center().sub(tileSize * 0.5, tileSize).freeze(); // 0.5 to center, 1 to move up (down is teh navbar)
|
||||
|
||||
final double playerX = pos.getVisualX();
|
||||
final double playerY = pos.getVisualY();
|
||||
|
||||
// total map area
|
||||
//@formatter:off
|
||||
final RectConst mapRect = vpCenter.startRect().grow(
|
||||
playerX*tileSize,
|
||||
(getWidth() - playerX) * tileSize,
|
||||
playerY*tileSize,
|
||||
(getHeight() - playerY) * tileSize
|
||||
).freeze();
|
||||
//@formatter:on
|
||||
|
||||
// tiles to render
|
||||
final int x1 = (int) Math.floor(playerX - (vpW / tileSize / 2));
|
||||
|
||||
final int y1 = (int) Math.floor(playerY - (vpH / tileSize / 2));
|
||||
final int x2 = (int) Math.ceil(playerX + (vpW / tileSize / 2));
|
||||
final int y2 = (int) Math.ceil(playerY + (vpH / tileSize / 2));
|
||||
|
||||
final TileRenderContext trc = new TileRenderContext(this, mapRect); //-tileSize*0.5
|
||||
|
||||
// batch rendering of the tiles
|
||||
if (USE_BATCH_RENDERING) {
|
||||
Render.enterBatchTexturedQuadMode(Res.getTexture("tiles"));
|
||||
}
|
||||
|
||||
for (trc.y = y1; trc.y <= y2; trc.y++) {
|
||||
for (trc.x = x1; trc.x <= x2; trc.x++) {
|
||||
trc.renderTile();
|
||||
}
|
||||
}
|
||||
|
||||
if (USE_BATCH_RENDERING) {
|
||||
Render.leaveBatchTexturedQuadMode();
|
||||
}
|
||||
|
||||
// render extras
|
||||
for (trc.y = y1; trc.y <= y2; trc.y++) {
|
||||
for (trc.x = x1; trc.x <= x2; trc.x++) {
|
||||
trc.renderItems();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Entity getEntity(int eid)
|
||||
{
|
||||
return entity_map.get(eid);
|
||||
}
|
||||
|
||||
|
||||
public void addEntity(Entity entity)
|
||||
{
|
||||
entity_map.put(entity.getEID(), entity);
|
||||
entity_set.add(entity);
|
||||
}
|
||||
|
||||
|
||||
public void removeEntity(Entity entity)
|
||||
{
|
||||
entity_map.remove(entity.getEID());
|
||||
entity_set.remove(entity);
|
||||
}
|
||||
|
||||
|
||||
public void removeEntity(int eid)
|
||||
{
|
||||
final Entity removed = entity_map.remove(eid);
|
||||
entity_set.remove(removed);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package mightypork.rogue.world.map;
|
||||
package mightypork.rogue.world.level;
|
||||
|
||||
|
||||
import mightypork.rogue.world.tile.Tile;
|
||||
+2
-1
@@ -1,6 +1,7 @@
|
||||
package mightypork.rogue.world.map;
|
||||
package mightypork.rogue.world.level.render;
|
||||
|
||||
|
||||
import mightypork.rogue.world.level.MapAccess;
|
||||
import mightypork.util.constraints.rect.Rect;
|
||||
|
||||
|
||||
+2
-1
@@ -1,6 +1,7 @@
|
||||
package mightypork.rogue.world.map;
|
||||
package mightypork.rogue.world.level.render;
|
||||
|
||||
|
||||
import mightypork.rogue.world.level.MapAccess;
|
||||
import mightypork.util.constraints.rect.Rect;
|
||||
import mightypork.util.constraints.rect.builders.TiledRect;
|
||||
|
||||
+9
-4
@@ -1,6 +1,7 @@
|
||||
package mightypork.rogue.world.map;
|
||||
package mightypork.rogue.world.level.render;
|
||||
|
||||
|
||||
import mightypork.rogue.world.level.MapAccess;
|
||||
import mightypork.rogue.world.tile.Tile;
|
||||
import mightypork.util.constraints.rect.Rect;
|
||||
import mightypork.util.constraints.rect.proxy.RectBound;
|
||||
@@ -60,11 +61,15 @@ public final class TileRenderContext extends MapRenderContext implements RectBou
|
||||
}
|
||||
|
||||
|
||||
public void render()
|
||||
public void renderTile()
|
||||
{
|
||||
map.getTile(x, y).render(this);
|
||||
map.getTile(x, y).renderTile(this);
|
||||
}
|
||||
|
||||
public void renderItems()
|
||||
{
|
||||
map.getTile(x, y).renderItems(this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Rect of the current tile to draw
|
||||
@@ -1,248 +0,0 @@
|
||||
package mightypork.rogue.world.map;
|
||||
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import mightypork.rogue.world.PlayerEntity;
|
||||
import mightypork.rogue.world.WorldAccess;
|
||||
import mightypork.rogue.world.WorldEntity;
|
||||
import mightypork.rogue.world.WorldPos;
|
||||
import mightypork.rogue.world.tile.Tile;
|
||||
import mightypork.rogue.world.tile.TileModel;
|
||||
import mightypork.rogue.world.tile.Tiles;
|
||||
import mightypork.util.ion.IonBinary;
|
||||
import mightypork.util.ion.IonBundle;
|
||||
import mightypork.util.ion.IonInput;
|
||||
import mightypork.util.ion.IonOutput;
|
||||
import mightypork.util.math.noise.NoiseGen;
|
||||
|
||||
|
||||
/**
|
||||
* One level of the dungeon
|
||||
*
|
||||
* @author MightyPork
|
||||
*/
|
||||
public class Level implements MapAccess, IonBinary {
|
||||
|
||||
public static final int ION_MARK = 53;
|
||||
|
||||
private int width, height;
|
||||
|
||||
/** Array of tiles [y][x] */
|
||||
private Tile[][] tiles;
|
||||
|
||||
private final List<WorldEntity> entities = new ArrayList<>();
|
||||
|
||||
/** Level seed (used for generation and tile variation) */
|
||||
public long seed;
|
||||
|
||||
private transient NoiseGen noiseGen;
|
||||
|
||||
|
||||
public Level()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public Level(int width, int height)
|
||||
{
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
buildArray();
|
||||
}
|
||||
|
||||
|
||||
private void buildArray()
|
||||
{
|
||||
this.tiles = new Tile[height][width];
|
||||
}
|
||||
|
||||
|
||||
public void fill(short id)
|
||||
{
|
||||
fill(Tiles.get(id));
|
||||
}
|
||||
|
||||
|
||||
public void fill(TileModel model)
|
||||
{
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
tiles[y][x] = model.createTile();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final Tile getTile(int x, int y)
|
||||
{
|
||||
if (x < 0 || x >= width || y < 0 || y >= height) return Tiles.NULL_SOLID.createTile(); // out of range
|
||||
|
||||
return tiles[y][x];
|
||||
}
|
||||
|
||||
|
||||
public final void setTile(TileModel model, int x, int y)
|
||||
{
|
||||
setTile(model.createTile(), x, y);
|
||||
}
|
||||
|
||||
|
||||
public final void setTile(int tileId, int x, int y)
|
||||
{
|
||||
setTile(new Tile(tileId), x, y);
|
||||
}
|
||||
|
||||
|
||||
public final void setTile(Tile tile, int x, int y)
|
||||
{
|
||||
if (x < 0 || x > width || y < 0 || y >= height) return; // out of range
|
||||
|
||||
tiles[y][x] = tile;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final int getWidth()
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final int getHeight()
|
||||
{
|
||||
return height;
|
||||
}
|
||||
|
||||
|
||||
public void setSeed(long seed)
|
||||
{
|
||||
this.seed = seed;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public long getSeed()
|
||||
{
|
||||
return seed;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void load(IonInput in) throws IOException
|
||||
{
|
||||
// metadata
|
||||
final IonBundle ib = in.readBundle();
|
||||
seed = ib.get("seed", 0L);
|
||||
width = ib.get("w", 0);
|
||||
height = ib.get("h", 0);
|
||||
|
||||
ib.loadSequence("entities", entities);
|
||||
|
||||
// init array of size
|
||||
buildArray();
|
||||
|
||||
// load tiles
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
// no mark
|
||||
tiles[y][x] = new Tile();
|
||||
tiles[y][x].load(in);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void save(IonOutput out) throws IOException
|
||||
{
|
||||
// metadata
|
||||
final IonBundle ib = new IonBundle();
|
||||
ib.put("seed", seed);
|
||||
ib.put("w", width);
|
||||
ib.put("h", height);
|
||||
ib.putSequence("entities", entities);
|
||||
out.writeBundle(ib);
|
||||
|
||||
// tiles (writing this way to save space)
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
// no mark to save space
|
||||
tiles[y][x].save(out);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public short getIonMark()
|
||||
{
|
||||
return ION_MARK;
|
||||
}
|
||||
|
||||
|
||||
public void updateLogic(WorldAccess world, double delta)
|
||||
{
|
||||
if (!world.isServer()) {
|
||||
throw new RuntimeException("Not allowed for client.");
|
||||
}
|
||||
|
||||
// just update them all
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
getTile(x, y).updateLogic(world, this, delta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update visuals for player (particle effects etc)
|
||||
*
|
||||
* @param world
|
||||
* @param player
|
||||
* @param delta
|
||||
*/
|
||||
public void updateVisual(WorldAccess world, PlayerEntity player, double delta)
|
||||
{
|
||||
if (world.isServer()) {
|
||||
throw new RuntimeException("Not allowed for server.");
|
||||
}
|
||||
|
||||
final int viewRange = player.getViewRange();
|
||||
final WorldPos eyepos = player.getViewPosition();
|
||||
|
||||
int x1 = eyepos.x - viewRange;
|
||||
int y1 = eyepos.y - viewRange;
|
||||
|
||||
int x2 = x1 + viewRange * 2;
|
||||
int y2 = y1 + viewRange * 2;
|
||||
|
||||
x1 = Math.min(Math.max(0, x1), width);
|
||||
y1 = Math.min(Math.max(0, y1), height);
|
||||
x2 = Math.min(x2, width);
|
||||
y2 = Math.max(y2, height);
|
||||
|
||||
for (int y = y1; y <= y2; y++) {
|
||||
for (int x = x1; x <= x2; x++) {
|
||||
getTile(x, y).updateVisual(world, this, delta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public NoiseGen getNoiseGen()
|
||||
{
|
||||
if (noiseGen == null) {
|
||||
noiseGen = new NoiseGen(0.2, 0, 0.5, 1, seed);
|
||||
}
|
||||
|
||||
return noiseGen;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package mightypork.rogue.world.map;
|
||||
|
||||
|
||||
import mightypork.rogue.world.WorldPos;
|
||||
|
||||
|
||||
public interface MapObserver {
|
||||
|
||||
int getViewRange();
|
||||
|
||||
|
||||
WorldPos getViewPosition();
|
||||
}
|
||||
@@ -2,12 +2,11 @@ package mightypork.rogue.world.tile;
|
||||
|
||||
|
||||
import mightypork.rogue.world.item.Item;
|
||||
import mightypork.rogue.world.map.TileRenderContext;
|
||||
import mightypork.rogue.world.level.render.TileRenderContext;
|
||||
import mightypork.util.constraints.rect.Rect;
|
||||
import mightypork.util.constraints.rect.proxy.RectBoundAdapter;
|
||||
import mightypork.util.control.timing.Animator;
|
||||
import mightypork.util.control.timing.AnimatorBounce;
|
||||
import mightypork.util.control.timing.Updateable;
|
||||
import mightypork.util.math.Easing;
|
||||
|
||||
|
||||
|
||||
@@ -4,11 +4,11 @@ package mightypork.rogue.world.tile;
|
||||
import java.io.IOException;
|
||||
import java.util.Stack;
|
||||
|
||||
import mightypork.rogue.world.WorldAccess;
|
||||
import mightypork.rogue.world.item.Item;
|
||||
import mightypork.rogue.world.map.Level;
|
||||
import mightypork.rogue.world.map.TileRenderContext;
|
||||
import mightypork.util.control.timing.Animator;
|
||||
import mightypork.rogue.world.level.Level;
|
||||
import mightypork.rogue.world.level.render.TileRenderContext;
|
||||
import mightypork.rogue.world.tile.models.TileModel;
|
||||
import mightypork.rogue.world.tile.renderers.TileRenderer;
|
||||
import mightypork.util.ion.IonBinary;
|
||||
import mightypork.util.ion.IonBundle;
|
||||
import mightypork.util.ion.IonInput;
|
||||
@@ -27,16 +27,13 @@ public final class Tile implements IonBinary {
|
||||
private TileModel model;
|
||||
private TileRenderer renderer;
|
||||
|
||||
public int id;
|
||||
private int id;
|
||||
|
||||
private final Stack<Item> items = new Stack<>();
|
||||
|
||||
/** persistent field for model, reflected by renderer */
|
||||
public final IonBundle metadata = new IonBundle();
|
||||
|
||||
/** non-persistent data field for model */
|
||||
public Object tmpdata;
|
||||
|
||||
|
||||
public Tile(int id)
|
||||
{
|
||||
@@ -63,7 +60,10 @@ public final class Tile implements IonBinary {
|
||||
}
|
||||
|
||||
|
||||
public void render(TileRenderContext context)
|
||||
/**
|
||||
* Render the tile alone (must not use other than the main map texture)
|
||||
*/
|
||||
public void renderTile(TileRenderContext context)
|
||||
{
|
||||
renderer.render(context);
|
||||
|
||||
@@ -73,6 +73,19 @@ public final class Tile implements IonBinary {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Render items
|
||||
* @param context
|
||||
*/
|
||||
public void renderItems(TileRenderContext context)
|
||||
{
|
||||
if (hasItems()) {
|
||||
renderer.renderItemOnTile(items.peek(), context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void save(IonOutput out) throws IOException
|
||||
{
|
||||
@@ -82,7 +95,7 @@ public final class Tile implements IonBinary {
|
||||
out.writeSequence(items);
|
||||
}
|
||||
|
||||
if (model.hasPersistentMetadata()) {
|
||||
if (model.hasMetadata()) {
|
||||
out.writeBundle(metadata);
|
||||
}
|
||||
}
|
||||
@@ -102,7 +115,7 @@ public final class Tile implements IonBinary {
|
||||
in.readSequence(items);
|
||||
}
|
||||
|
||||
if (model.hasPersistentMetadata()) {
|
||||
if (model.hasMetadata()) {
|
||||
in.readBundle(metadata);
|
||||
}
|
||||
}
|
||||
@@ -111,18 +124,12 @@ public final class Tile implements IonBinary {
|
||||
/**
|
||||
* Update tile logic state (on server)
|
||||
*
|
||||
* @param world the world
|
||||
* @param level the level
|
||||
* @param delta delta time
|
||||
*/
|
||||
public void updateLogic(WorldAccess world, Level level, double delta)
|
||||
public void update(Level level, double delta)
|
||||
{
|
||||
model.updateLogic(this, world, level, delta);
|
||||
}
|
||||
|
||||
|
||||
public void updateVisual(WorldAccess world, Level level, double delta)
|
||||
{
|
||||
model.updateVisual(this, world, level, delta);
|
||||
model.update(this, level, delta);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ package mightypork.rogue.world.tile;
|
||||
import mightypork.rogue.world.tile.models.Floor;
|
||||
import mightypork.rogue.world.tile.models.NullFloor;
|
||||
import mightypork.rogue.world.tile.models.NullWall;
|
||||
import mightypork.rogue.world.tile.models.TileModel;
|
||||
import mightypork.rogue.world.tile.models.Wall;
|
||||
|
||||
|
||||
@@ -35,7 +36,7 @@ public final class Tiles {
|
||||
public static final TileModel CRYSTAL_WALL = new Wall(11).setTexture("tile.wall.crystal");
|
||||
|
||||
|
||||
static void register(int id, TileModel model)
|
||||
public static void register(int id, TileModel model)
|
||||
{
|
||||
if (id < 0 || id >= tiles.length) {
|
||||
throw new IllegalArgumentException("Tile ID " + id + " is out of range.");
|
||||
|
||||
@@ -39,7 +39,7 @@ public abstract class AbstractNullTile extends SimpleTile {
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasPersistentMetadata()
|
||||
public boolean hasMetadata()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
package mightypork.rogue.world.tile.models;
|
||||
|
||||
|
||||
import mightypork.rogue.world.WorldAccess;
|
||||
import mightypork.rogue.world.map.Level;
|
||||
import mightypork.rogue.world.level.Level;
|
||||
import mightypork.rogue.world.tile.Tile;
|
||||
import mightypork.rogue.world.tile.TileModel;
|
||||
import mightypork.util.annotations.DefaultImpl;
|
||||
|
||||
|
||||
@@ -33,7 +31,7 @@ public abstract class SimpleTile extends TileModel {
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasPersistentMetadata()
|
||||
public boolean hasMetadata()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -41,13 +39,7 @@ public abstract class SimpleTile extends TileModel {
|
||||
|
||||
@Override
|
||||
@DefaultImpl
|
||||
public void updateLogic(Tile tile, WorldAccess world, Level level, double delta)
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
@DefaultImpl
|
||||
public void updateVisual(Tile tile, WorldAccess world, Level level, double delta)
|
||||
public void update(Tile tile, Level level, double delta)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
+8
-12
@@ -1,9 +1,11 @@
|
||||
package mightypork.rogue.world.tile;
|
||||
package mightypork.rogue.world.tile.models;
|
||||
|
||||
|
||||
import mightypork.rogue.world.WorldAccess;
|
||||
import mightypork.rogue.world.map.Level;
|
||||
import mightypork.rogue.world.level.Level;
|
||||
import mightypork.rogue.world.tile.Tile;
|
||||
import mightypork.rogue.world.tile.Tiles;
|
||||
import mightypork.rogue.world.tile.renderers.BasicTileRenderer;
|
||||
import mightypork.rogue.world.tile.renderers.TileRenderer;
|
||||
|
||||
|
||||
/**
|
||||
@@ -68,21 +70,15 @@ public abstract class TileModel {
|
||||
|
||||
|
||||
/**
|
||||
* Update tile in world, called by server
|
||||
* Update tile in world
|
||||
*/
|
||||
public abstract void updateLogic(Tile tile, WorldAccess world, Level level, double delta);
|
||||
|
||||
|
||||
/**
|
||||
* Update tile visuals (particles / update for renderer)
|
||||
*/
|
||||
public abstract void updateVisual(Tile tile, WorldAccess world, Level level, double delta);
|
||||
public abstract void update(Tile tile, Level level, double delta);
|
||||
|
||||
|
||||
/**
|
||||
* @return true if this item type has metadata worth saving
|
||||
*/
|
||||
public abstract boolean hasPersistentMetadata();
|
||||
public abstract boolean hasMetadata();
|
||||
|
||||
|
||||
/**
|
||||
@@ -4,13 +4,12 @@ package mightypork.rogue.world.tile.renderers;
|
||||
import mightypork.gamecore.render.Render;
|
||||
import mightypork.gamecore.render.textures.TxSheet;
|
||||
import mightypork.rogue.Res;
|
||||
import mightypork.rogue.world.map.TileRenderContext;
|
||||
import mightypork.rogue.world.tile.TileRenderer;
|
||||
import mightypork.rogue.world.level.render.TileRenderContext;
|
||||
|
||||
|
||||
public class BasicTileRenderer extends TileRenderer {
|
||||
|
||||
private TxSheet sheet;
|
||||
private final TxSheet sheet;
|
||||
|
||||
|
||||
public BasicTileRenderer(String sheetKey)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package mightypork.rogue.world.tile.renderers;
|
||||
|
||||
import mightypork.rogue.world.map.TileRenderContext;
|
||||
import mightypork.rogue.world.tile.TileRenderer;
|
||||
|
||||
import mightypork.rogue.world.level.render.TileRenderContext;
|
||||
|
||||
|
||||
public class NullTileRenderer extends TileRenderer {
|
||||
|
||||
+3
-3
@@ -1,9 +1,9 @@
|
||||
package mightypork.rogue.world.tile;
|
||||
package mightypork.rogue.world.tile.renderers;
|
||||
|
||||
|
||||
import mightypork.rogue.world.item.Item;
|
||||
import mightypork.rogue.world.map.TileRenderContext;
|
||||
import mightypork.rogue.world.tile.renderers.NullTileRenderer;
|
||||
import mightypork.rogue.world.level.render.TileRenderContext;
|
||||
import mightypork.rogue.world.tile.DroppedItemRenderer;
|
||||
|
||||
|
||||
/**
|
||||
@@ -42,6 +42,29 @@ public class IonBundle implements IonBinary {
|
||||
}
|
||||
|
||||
|
||||
public void loadBundle(String key, IonBundle bundle)
|
||||
{
|
||||
if (!containsKey(key)) return;
|
||||
|
||||
final IonBundle ib = get(key, null);
|
||||
|
||||
bundle.clear();
|
||||
bundle.putAll(ib);
|
||||
}
|
||||
|
||||
|
||||
public boolean containsKey(Object key)
|
||||
{
|
||||
return backingMap.containsKey(key);
|
||||
}
|
||||
|
||||
|
||||
public boolean containsValue(Object value)
|
||||
{
|
||||
return backingMap.containsValue(value);
|
||||
}
|
||||
|
||||
|
||||
public <K, V> Map<K, V> getMap(String key)
|
||||
{
|
||||
final Map<K, V> m = new HashMap<>();
|
||||
@@ -50,12 +73,12 @@ public class IonBundle implements IonBinary {
|
||||
}
|
||||
|
||||
|
||||
public <K, V> void loadMap(String key, Map<K, V> map)
|
||||
public <K, V> void loadMap(String key, Map<K, V> filled)
|
||||
{
|
||||
final IonMapWrapper imw = get(key, null);
|
||||
if (imw == null) return;
|
||||
map.clear();
|
||||
imw.fill(map);
|
||||
filled.clear();
|
||||
imw.fill(filled);
|
||||
}
|
||||
|
||||
|
||||
@@ -67,12 +90,12 @@ public class IonBundle implements IonBinary {
|
||||
}
|
||||
|
||||
|
||||
public <E> void loadSequence(String key, Collection<E> sequence)
|
||||
public <E> void loadSequence(String key, Collection<E> filled)
|
||||
{
|
||||
final IonSequenceWrapper isw = get(key, null);
|
||||
if (isw == null) return;
|
||||
sequence.clear();
|
||||
isw.fill(sequence);
|
||||
filled.clear();
|
||||
isw.fill(filled);
|
||||
}
|
||||
|
||||
|
||||
@@ -262,6 +285,12 @@ public class IonBundle implements IonBinary {
|
||||
}
|
||||
|
||||
|
||||
public void putAll(IonBundle otherBundle)
|
||||
{
|
||||
backingMap.putAll(otherBundle.backingMap);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
|
||||
@@ -224,7 +224,7 @@ public class IonInput {
|
||||
*/
|
||||
public IonBundle readBundle() throws IOException
|
||||
{
|
||||
IonBundle ib = new IonBundle();
|
||||
final IonBundle ib = new IonBundle();
|
||||
ib.load(this);
|
||||
return ib;
|
||||
}
|
||||
|
||||
@@ -270,7 +270,7 @@ public class IonOutput {
|
||||
}
|
||||
|
||||
if (obj instanceof IonBundled) {
|
||||
throw new IOException("Bundled objects cannot be written to ION stream directly.");
|
||||
throw new IOException("Bundled objects cannot be written to ION stream directly at " + obj);
|
||||
}
|
||||
|
||||
if (obj instanceof Boolean) {
|
||||
|
||||
Reference in New Issue
Block a user