mirror of
https://github.com/collinsmith/riiablo.git
synced 2025-07-09 15:28:18 +07:00
removed some unnecessary files
This commit is contained in:
@ -1,26 +0,0 @@
|
||||
package gdx.diablo.assets;
|
||||
|
||||
public class AssetDescriptor<T> {
|
||||
public static <T> AssetDescriptor<T> of(String fileName, Class<T> type) {
|
||||
return of(fileName, type, null);
|
||||
}
|
||||
|
||||
public static <T> AssetDescriptor<T> of(String fileName, Class<T> type, AssetLoader.Parameters<T> params) {
|
||||
return new AssetDescriptor<>(fileName, type, params);
|
||||
}
|
||||
|
||||
public final String fileName;
|
||||
public final Class<T> type;
|
||||
public final AssetLoader.Parameters params;
|
||||
|
||||
public AssetDescriptor(String fileName, Class<T> type, AssetLoader.Parameters<T> params) {
|
||||
this.fileName = fileName.replace('\\', '/');
|
||||
this.type = type;
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return fileName + ", " + type.getName();
|
||||
}
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
package gdx.diablo.assets;
|
||||
|
||||
import com.badlogic.gdx.assets.loaders.FileHandleResolver;
|
||||
import com.badlogic.gdx.files.FileHandle;
|
||||
|
||||
public abstract class AssetLoader<T, P extends AssetLoader.Parameters<T>> {
|
||||
private FileHandleResolver resolver;
|
||||
|
||||
public AssetLoader(FileHandleResolver resolver) {
|
||||
this.resolver = resolver;
|
||||
}
|
||||
|
||||
public FileHandle resolve(String fileName) {
|
||||
return resolver.resolve(fileName);
|
||||
}
|
||||
|
||||
public interface Parameters<T> {}
|
||||
}
|
@ -1,45 +0,0 @@
|
||||
package gdx.diablo.assets.async;
|
||||
|
||||
import com.badlogic.gdx.utils.Disposable;
|
||||
import com.badlogic.gdx.utils.GdxRuntimeException;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class AsyncExecutor implements Disposable {
|
||||
private final ExecutorService executor;
|
||||
|
||||
public AsyncExecutor(int maxConcurrent) {
|
||||
executor = Executors.newFixedThreadPool(maxConcurrent, new ThreadFactory() {
|
||||
@Override
|
||||
public Thread newThread(Runnable r) {
|
||||
Thread thread = new Thread(r, "AsyncExecutor-Thread");
|
||||
thread.setDaemon(true);
|
||||
return thread;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
executor.shutdown();
|
||||
try {
|
||||
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
throw new GdxRuntimeException("Couldn't shutdown loading thread", e);
|
||||
}
|
||||
}
|
||||
|
||||
public <T> AsyncResult<T> submit(final AsyncTask<T> task) {
|
||||
if (executor.isShutdown()) throw new GdxRuntimeException("Cannot run tasks on an executor that has been shutdown (disposed)");
|
||||
return new AsyncResult<>(executor.submit(new Callable<T>() {
|
||||
@Override
|
||||
public T call() throws Exception {
|
||||
return task.call();
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
package gdx.diablo.assets.async;
|
||||
|
||||
import com.badlogic.gdx.utils.GdxRuntimeException;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public class AsyncResult<T> {
|
||||
private final Future<T> future;
|
||||
|
||||
AsyncResult(Future<T> future) {
|
||||
this.future = future;
|
||||
}
|
||||
|
||||
public boolean isDown() {
|
||||
return future.isDone();
|
||||
}
|
||||
|
||||
public T get() {
|
||||
try {
|
||||
return future.get();
|
||||
} catch (InterruptedException e) {
|
||||
return null;
|
||||
} catch (ExecutionException e) {
|
||||
throw new GdxRuntimeException(e.getCause());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
package gdx.diablo.assets.async;
|
||||
|
||||
public interface AsyncTask<T> {
|
||||
T call() throws Exception;
|
||||
}
|
7
core/src/gdx/diablo/engine/component/LayerComponent.java
Normal file
7
core/src/gdx/diablo/engine/component/LayerComponent.java
Normal file
@ -0,0 +1,7 @@
|
||||
package gdx.diablo.engine.component;
|
||||
|
||||
public class LayerComponent {
|
||||
|
||||
private LayerComponent() {}
|
||||
|
||||
}
|
7
core/src/gdx/diablo/engine/component/ModeComponent.java
Normal file
7
core/src/gdx/diablo/engine/component/ModeComponent.java
Normal file
@ -0,0 +1,7 @@
|
||||
package gdx.diablo.engine.component;
|
||||
|
||||
public class ModeComponent {
|
||||
|
||||
private ModeComponent() {}
|
||||
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package gdx.diablo.engine.component;
|
||||
|
||||
public class PositionComponent {
|
||||
|
||||
private PositionComponent() {}
|
||||
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package gdx.diablo.engine.component;
|
||||
|
||||
public class VelocityComponent {
|
||||
|
||||
private VelocityComponent() {}
|
||||
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package gdx.diablo.engine.component;
|
||||
|
||||
public class WeaponClassComponent {
|
||||
|
||||
private WeaponClassComponent() {}
|
||||
|
||||
}
|
7
core/src/gdx/diablo/engine/system/MovementSystem.java
Normal file
7
core/src/gdx/diablo/engine/system/MovementSystem.java
Normal file
@ -0,0 +1,7 @@
|
||||
package gdx.diablo.engine.system;
|
||||
|
||||
public class MovementSystem {
|
||||
|
||||
private MovementSystem() {}
|
||||
|
||||
}
|
21
core/src/gdx/diablo/engine/system/RenderSysem.java
Normal file
21
core/src/gdx/diablo/engine/system/RenderSysem.java
Normal file
@ -0,0 +1,21 @@
|
||||
package gdx.diablo.engine.system;
|
||||
|
||||
import com.badlogic.ashley.core.ComponentMapper;
|
||||
import com.badlogic.ashley.core.Entity;
|
||||
import com.badlogic.ashley.core.Family;
|
||||
import com.badlogic.ashley.systems.IteratingSystem;
|
||||
|
||||
import gdx.diablo.engine.component.WeaponClassComponent;
|
||||
|
||||
public class WeaponSystem extends IteratingSystem {
|
||||
private ComponentMapper<WeaponClassComponent> wc = ComponentMapper.getFor(WeaponClassComponent.class);
|
||||
|
||||
public WeaponSystem() {
|
||||
super(Family.all(WeaponClassComponent.class).get());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processEntity(Entity entity, float delta) {
|
||||
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
package gdx.diablo.entity2;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
|
||||
public enum Component {
|
||||
HD,
|
||||
TR,
|
||||
LG,
|
||||
RA,
|
||||
LA,
|
||||
RH,
|
||||
LH,
|
||||
SH,
|
||||
S1,
|
||||
S2,
|
||||
S3,
|
||||
S4,
|
||||
S5,
|
||||
S6,
|
||||
S7,
|
||||
S8;
|
||||
|
||||
public static Component valueOf(int i) {
|
||||
switch (i) {
|
||||
case 0x0: return HD;
|
||||
case 0x1: return TR;
|
||||
case 0x2: return LG;
|
||||
case 0x3: return RA;
|
||||
case 0x4: return LA;
|
||||
case 0x5: return RH;
|
||||
case 0x6: return LH;
|
||||
case 0x7: return SH;
|
||||
case 0x8: return S1;
|
||||
case 0x9: return S2;
|
||||
case 0xA: return S3;
|
||||
case 0xB: return S4;
|
||||
case 0xC: return S5;
|
||||
case 0xD: return S6;
|
||||
case 0xE: return S7;
|
||||
case 0xF: return S8;
|
||||
default:
|
||||
Gdx.app.error("Component", "Unknown component: " + i);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,87 +0,0 @@
|
||||
package gdx.diablo.entity2;
|
||||
|
||||
import com.badlogic.gdx.graphics.g2d.Batch;
|
||||
import com.badlogic.gdx.math.Vector2;
|
||||
|
||||
import java.util.EnumMap;
|
||||
|
||||
import gdx.diablo.codec.Animation;
|
||||
import gdx.diablo.graphics.PaletteIndexedBatch;
|
||||
|
||||
public class Entity {
|
||||
|
||||
/**
|
||||
* x, y (src)
|
||||
* angle (radians)
|
||||
* scalar (movement speed)
|
||||
*
|
||||
* x, y (dst)
|
||||
*/
|
||||
Vector2 origin;
|
||||
Vector2 velocity;
|
||||
|
||||
String mode;
|
||||
String code;
|
||||
String armorType;
|
||||
String weaponClass;
|
||||
|
||||
EnumMap<Component, Animation.Layer> components = new EnumMap<>(Component.class);
|
||||
Animation.COFAnimation animation;
|
||||
|
||||
Entity() {
|
||||
mode = code = "NU";
|
||||
armorType = "LIT";
|
||||
weaponClass = "HTH";
|
||||
}
|
||||
|
||||
public void setMode(String mode) {
|
||||
setMode(mode, mode);
|
||||
}
|
||||
|
||||
public void setMode(String mode, String code) {
|
||||
this.mode = mode;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
/*
|
||||
Entity(Excel<M> excel, String mode) {
|
||||
this(excel.get(mode));
|
||||
}
|
||||
|
||||
Entity(Excel<M> excel) {
|
||||
this(excel, "NU");
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
public M getMode() {
|
||||
return mode;
|
||||
}
|
||||
|
||||
public void setMode(M mode) {
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return mode.getCode();
|
||||
}
|
||||
*/
|
||||
|
||||
public int getX() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getY() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void setComponent(Component component, Animation.Layer value) {
|
||||
}
|
||||
|
||||
public void draw(Batch batch) {
|
||||
draw((PaletteIndexedBatch) batch);
|
||||
}
|
||||
|
||||
public void draw(PaletteIndexedBatch batch) {
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
package gdx.diablo.entity2;
|
||||
|
||||
public class Object extends Entity {
|
||||
public Object() {
|
||||
//super(Diablo.files.ObjMode);
|
||||
}
|
||||
}
|
@ -1,115 +0,0 @@
|
||||
package gdx.diablo.entity2;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
|
||||
import java.util.EnumMap;
|
||||
|
||||
import gdx.diablo.codec.excel.Weapons;
|
||||
import gdx.diablo.item.BodyLoc;
|
||||
import gdx.diablo.item.Item;
|
||||
|
||||
public class Player extends Entity {
|
||||
private static final String TAG = "Player";
|
||||
|
||||
public enum Slot {
|
||||
HEAD,
|
||||
NECK,
|
||||
TORS,
|
||||
RARM,
|
||||
LARM,
|
||||
RRIN,
|
||||
LRIN,
|
||||
BELT,
|
||||
FEET,
|
||||
GLOV;
|
||||
}
|
||||
|
||||
boolean dirty;
|
||||
boolean alternate;
|
||||
EnumMap<BodyLoc, Item> equipped = new EnumMap<>(BodyLoc.class);
|
||||
|
||||
public Player() {
|
||||
//super(Diablo.files.PlrMode);
|
||||
}
|
||||
|
||||
public Item getSlot(Slot slot) {
|
||||
switch (slot) {
|
||||
case HEAD: return equipped.get(BodyLoc.HEAD);
|
||||
case NECK: return equipped.get(BodyLoc.NECK);
|
||||
case TORS: return equipped.get(BodyLoc.TORS);
|
||||
case RARM: return equipped.get(alternate ? BodyLoc.RARM2 : BodyLoc.RARM);
|
||||
case LARM: return equipped.get(alternate ? BodyLoc.LARM2 : BodyLoc.LARM);
|
||||
case RRIN: return equipped.get(BodyLoc.RRIN);
|
||||
case LRIN: return equipped.get(BodyLoc.LRIN);
|
||||
case BELT: return equipped.get(BodyLoc.BELT);
|
||||
case FEET: return equipped.get(BodyLoc.FEET);
|
||||
case GLOV: return equipped.get(BodyLoc.GLOV);
|
||||
default:
|
||||
Gdx.app.error(TAG, "Invalid slot: " + slot);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void update() {
|
||||
if (!dirty) {
|
||||
return;
|
||||
} else {
|
||||
dirty = false;
|
||||
}
|
||||
|
||||
Item rArm = getSlot(Slot.RARM);
|
||||
if (rArm != null && rArm.type.is("weap")) {
|
||||
Weapons.Entry entry = rArm.getBase();
|
||||
if (entry._2handed) {
|
||||
weaponClass = entry._2handedwclass;
|
||||
} else {
|
||||
weaponClass = entry.wclass;
|
||||
}
|
||||
} else {
|
||||
weaponClass = "HTH";
|
||||
}
|
||||
|
||||
Item lArm = getSlot(Slot.LARM);
|
||||
if (lArm != null) {
|
||||
if (lArm.type.is("weap") && rArm != null && rArm.type.is("weap")) {
|
||||
|
||||
} else if (lArm.type.is("shld")) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (lArm != null && lArm.type.is("weap")) {
|
||||
weaponClass = ((Weapons.Entry) lArm.base).wclass;
|
||||
}
|
||||
|
||||
// TODO: add support for barb (1js,1jt,1ss,1st) / assassin (ht1,ht2) customs
|
||||
Item weapon = null;
|
||||
if (rArm != null && rArm.type.is("weap")) {
|
||||
weapon = rArm;
|
||||
} else if (lArm != null && lArm.type.is("weap")) {
|
||||
weapon = lArm;
|
||||
}
|
||||
|
||||
String wclass = null;
|
||||
if (weapon == null) {
|
||||
wclass = "hth";
|
||||
} else {
|
||||
Weapons.Entry weaponEntry = weapon.getBase();
|
||||
wclass = weaponEntry.wclass;
|
||||
}
|
||||
|
||||
// TODO: custom code for barbarian _1or2handed
|
||||
if (rArm != null && lArm != null) {
|
||||
// if rArm and lArm are weapons
|
||||
// if only one is weapon
|
||||
/*
|
||||
if (rArm.type.is("weap")) {
|
||||
Weapons.Entry rArmEntry = rArm.getBase();
|
||||
|
||||
}
|
||||
*/
|
||||
} else if (rArm != null) {
|
||||
} else if (lArm != null) {
|
||||
}
|
||||
}
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
package gdx.diablo.entity3;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
|
||||
public enum Component {
|
||||
HD,
|
||||
TR,
|
||||
LG,
|
||||
RA,
|
||||
LA,
|
||||
RH,
|
||||
LH,
|
||||
SH,
|
||||
S1,
|
||||
S2,
|
||||
S3,
|
||||
S4,
|
||||
S5,
|
||||
S6,
|
||||
S7,
|
||||
S8;
|
||||
|
||||
public static Component valueOf(int i) {
|
||||
switch (i) {
|
||||
case 0x0: return HD;
|
||||
case 0x1: return TR;
|
||||
case 0x2: return LG;
|
||||
case 0x3: return RA;
|
||||
case 0x4: return LA;
|
||||
case 0x5: return RH;
|
||||
case 0x6: return LH;
|
||||
case 0x7: return SH;
|
||||
case 0x8: return S1;
|
||||
case 0x9: return S2;
|
||||
case 0xA: return S3;
|
||||
case 0xB: return S4;
|
||||
case 0xC: return S5;
|
||||
case 0xD: return S6;
|
||||
case 0xE: return S7;
|
||||
case 0xF: return S8;
|
||||
default:
|
||||
Gdx.app.error("Component", "Unknown component: " + i);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,337 +0,0 @@
|
||||
package gdx.diablo.entity3;
|
||||
|
||||
import android.support.annotation.CallSuper;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.assets.AssetDescriptor;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.g2d.Batch;
|
||||
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
|
||||
import com.badlogic.gdx.math.GridPoint2;
|
||||
import com.badlogic.gdx.math.MathUtils;
|
||||
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import gdx.diablo.Diablo;
|
||||
import gdx.diablo.codec.Animation;
|
||||
import gdx.diablo.codec.COF;
|
||||
import gdx.diablo.codec.COFD2;
|
||||
import gdx.diablo.codec.DCC;
|
||||
import gdx.diablo.entity.Direction;
|
||||
import gdx.diablo.graphics.PaletteIndexedBatch;
|
||||
import gdx.diablo.item.Item;
|
||||
import gdx.diablo.map.DS1;
|
||||
import gdx.diablo.map.DT1.Tile;
|
||||
|
||||
public class Entity {
|
||||
private static final String TAG = "Entity";
|
||||
private static final boolean DEBUG = true;
|
||||
private static final boolean DEBUG_COMPONENTS = DEBUG && true;
|
||||
private static final boolean DEBUG_DIRTY = DEBUG && true;
|
||||
private static final boolean DEBUG_ASSETS = DEBUG && true;
|
||||
private static final boolean DEBUG_WCLASS = DEBUG && true;
|
||||
|
||||
protected enum EntType {
|
||||
OBJECT,
|
||||
MONSTER,
|
||||
CHARS;
|
||||
|
||||
public final String PATH = "data\\global\\" + name() + "\\";
|
||||
}
|
||||
|
||||
public static final class Dirty {
|
||||
public static final int NONE = 0;
|
||||
public static final int HD = 1 << 0;
|
||||
public static final int TR = 1 << 1;
|
||||
public static final int LG = 1 << 2;
|
||||
public static final int RA = 1 << 3;
|
||||
public static final int LA = 1 << 4;
|
||||
public static final int RH = 1 << 5;
|
||||
public static final int LH = 1 << 6;
|
||||
public static final int SH = 1 << 7;
|
||||
public static final int S1 = 1 << 8;
|
||||
public static final int S2 = 1 << 9;
|
||||
public static final int S3 = 1 << 10;
|
||||
public static final int S4 = 1 << 11;
|
||||
public static final int S5 = 1 << 12;
|
||||
public static final int S6 = 1 << 13;
|
||||
public static final int S7 = 1 << 14;
|
||||
public static final int S8 = 1 << 15;
|
||||
|
||||
public static String toString(int bits) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if (bits == NONE) {
|
||||
builder.append("NONE");
|
||||
} else {
|
||||
if ((bits & HD) == HD) builder.append("HD").append("|");
|
||||
if ((bits & TR) == TR) builder.append("TR").append("|");
|
||||
if ((bits & LG) == LG) builder.append("LG").append("|");
|
||||
if ((bits & RA) == RA) builder.append("RA").append("|");
|
||||
if ((bits & LA) == LA) builder.append("LA").append("|");
|
||||
if ((bits & RH) == RH) builder.append("RH").append("|");
|
||||
if ((bits & LH) == LH) builder.append("LH").append("|");
|
||||
if ((bits & SH) == SH) builder.append("SH").append("|");
|
||||
if ((bits & S1) == S1) builder.append("S1").append("|");
|
||||
if ((bits & S2) == S2) builder.append("S2").append("|");
|
||||
if ((bits & S3) == S3) builder.append("S3").append("|");
|
||||
if ((bits & S4) == S4) builder.append("S4").append("|");
|
||||
if ((bits & S5) == S5) builder.append("S5").append("|");
|
||||
if ((bits & S6) == S6) builder.append("S6").append("|");
|
||||
if ((bits & S7) == S7) builder.append("S7").append("|");
|
||||
if ((bits & S8) == S8) builder.append("S8").append("|");
|
||||
if (builder.length() > 0) builder.setLength(builder.length() - 1);
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
|
||||
private final int ALL_DIRTY = 0x0000FFFF;
|
||||
protected static final String DEFAULT_LAYER = "LIT";
|
||||
private static final String[] DEFAULT_LAYERS;
|
||||
static {
|
||||
DEFAULT_LAYERS = new String[16];
|
||||
Arrays.fill(DEFAULT_LAYERS, DEFAULT_LAYER);
|
||||
}
|
||||
|
||||
GridPoint2 origin = new GridPoint2();
|
||||
float angle = MathUtils.PI * 3 / 2;
|
||||
|
||||
int dirty;
|
||||
String type;
|
||||
String mode;
|
||||
String code;
|
||||
String layers[];
|
||||
String weaponClass;
|
||||
|
||||
EntType entType;
|
||||
Animation animation;
|
||||
|
||||
Entity(String type) {
|
||||
this(type, EntType.OBJECT);
|
||||
}
|
||||
|
||||
Entity(String type, EntType entType) {
|
||||
this.type = type;
|
||||
this.entType = entType;
|
||||
mode = code = "NU";
|
||||
weaponClass = "HTH";
|
||||
layers = DEFAULT_LAYERS;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
public static Entity create(DS1 ds1, DS1.Object obj) {
|
||||
final int type = obj.type;
|
||||
switch (type) {
|
||||
case DS1.Object.DYNAMIC_TYPE:
|
||||
throw new UnsupportedOperationException("Unsupported type: " + type);
|
||||
case DS1.Object.STATIC_TYPE:
|
||||
return null;
|
||||
default:
|
||||
throw new AssertionError("Unsupported type: " + type);
|
||||
}
|
||||
}
|
||||
|
||||
public void setMode(String mode) {
|
||||
setMode(mode, mode);
|
||||
}
|
||||
|
||||
public void setMode(String mode, String code) {
|
||||
if (!this.mode.equals(mode)) {
|
||||
this.mode = mode;
|
||||
invalidate();
|
||||
}
|
||||
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public void setWeaponClass(String wclass) {
|
||||
if (!weaponClass.equals(wclass)) {
|
||||
if (DEBUG_WCLASS) Gdx.app.debug(TAG, "wclass: " + weaponClass + " -> " + wclass);
|
||||
weaponClass = wclass;
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public void setArmType(Component component, String armType) {
|
||||
if (layers == DEFAULT_LAYERS) {
|
||||
if (!armType.equalsIgnoreCase(DEFAULT_LAYER)) {
|
||||
layers = ArrayUtils.clone(DEFAULT_LAYERS);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int ordinal = component.ordinal();
|
||||
if (layers[ordinal].equalsIgnoreCase(armType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (DEBUG_COMPONENTS) Gdx.app.debug(TAG, "layer " + ordinal + " " + layers[ordinal] + " -> " + armType);
|
||||
layers[ordinal] = armType;
|
||||
dirty |= (1 << ordinal);
|
||||
}
|
||||
|
||||
protected Item getItem(Component component) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final void invalidate() {
|
||||
dirty = ALL_DIRTY;
|
||||
}
|
||||
|
||||
public final void validate() {
|
||||
if (dirty == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
@CallSuper
|
||||
protected void update() {
|
||||
String path = type + mode + weaponClass;
|
||||
Gdx.app.log(TAG, path);
|
||||
|
||||
COF cof = getCOFs().lookup(path);
|
||||
Gdx.app.log(TAG, ObjectUtils.toString(cof));
|
||||
|
||||
boolean changed;
|
||||
if (animation == null) {
|
||||
animation = Animation.newAnimation(cof);
|
||||
changed = true;
|
||||
} else {
|
||||
changed = animation.reset(cof);
|
||||
}
|
||||
|
||||
if (changed) {
|
||||
dirty = ALL_DIRTY;
|
||||
animation.setDirection(getDirection());
|
||||
}
|
||||
|
||||
if (DEBUG_DIRTY) Gdx.app.debug(TAG, "dirty layers: " + Dirty.toString(dirty));
|
||||
for (int l = 0; l < cof.getNumLayers(); l++) {
|
||||
COF.Layer layer = cof.getLayer(l);
|
||||
if (((1 << layer.component) & dirty) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final int c = layer.component;
|
||||
final Component comp = Component.valueOf(c);
|
||||
if (comp == null) continue;
|
||||
String component = comp.name();
|
||||
String armType = layers[c];
|
||||
String weaponClass = layer.weaponClass;
|
||||
path = entType.PATH + type + "\\" + component + "\\" + type + component + armType + mode + weaponClass + ".dcc";
|
||||
if (armType.isEmpty()) {
|
||||
animation.setLayer(c, null);
|
||||
continue;
|
||||
}
|
||||
Gdx.app.log(TAG, path);
|
||||
|
||||
if (DEBUG_ASSETS) {
|
||||
final AssetDescriptor<DCC> descriptor = new AssetDescriptor<>(path, DCC.class);
|
||||
Diablo.assets.load(descriptor);
|
||||
Diablo.assets.finishLoadingAsset(descriptor);
|
||||
DCC dcc = Diablo.assets.get(descriptor);
|
||||
animation.setLayer(c, dcc);
|
||||
|
||||
/*Runnable loader = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!Diablo.assets.isLoaded(descriptor)) {
|
||||
Gdx.app.postRunnable(this);
|
||||
return;
|
||||
}
|
||||
|
||||
DCC dcc = Diablo.assets.get(descriptor);
|
||||
animation.setLayer(c, dcc);
|
||||
|
||||
Item item = getItem(comp);
|
||||
if (item != null) {
|
||||
animation.getLayer(c).setTransform(item.charColormap, item.charColorIndex);
|
||||
}
|
||||
}
|
||||
};*/
|
||||
//Gdx.app.postRunnable(loader);
|
||||
}
|
||||
|
||||
//if (BodyLoc.TORS.contains(c)) {
|
||||
Item item = getItem(comp);
|
||||
if (item != null) {
|
||||
// FIXME: colors don't look right for sorc Tirant circlet changing hair color
|
||||
// putting a ruby in a white circlet not change color on item or character
|
||||
// circlets and other items with hidden magic level might work different?
|
||||
animation.getLayer(layer.component).setTransform(item.charColormap, item.charColorIndex);
|
||||
//System.out.println(item.getName() + ": " + item.charColormap + " ; " + item.charColorIndex);
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
dirty = 0;
|
||||
}
|
||||
|
||||
protected COFD2 getCOFs() {
|
||||
return Diablo.cofs.active;
|
||||
}
|
||||
|
||||
public void drawDebug(ShapeRenderer shapes) {
|
||||
float x = +(origin.x * Tile.SUBTILE_WIDTH50) - (origin.y * Tile.SUBTILE_WIDTH50);
|
||||
float y = -(origin.x * Tile.SUBTILE_HEIGHT50) - (origin.y * Tile.SUBTILE_HEIGHT50);
|
||||
|
||||
final float R = 32;
|
||||
shapes.setColor(Color.RED);
|
||||
shapes.line(x, y, x + MathUtils.cos(angle) * R, y + MathUtils.sin(angle) * R);
|
||||
|
||||
float rounded = Direction.radiansToDirection16Radians(angle);
|
||||
shapes.setColor(Color.GREEN);
|
||||
shapes.line(x, y, x + MathUtils.cos(rounded) * R * 0.5f, y + MathUtils.sin(rounded) * R * 0.5f);
|
||||
}
|
||||
|
||||
public void draw(Batch batch) {
|
||||
draw((PaletteIndexedBatch) batch);
|
||||
}
|
||||
|
||||
public void draw(PaletteIndexedBatch batch) {
|
||||
validate();
|
||||
animation.act();
|
||||
float x = +(origin.x * Tile.SUBTILE_WIDTH50) - (origin.y * Tile.SUBTILE_WIDTH50);
|
||||
float y = -(origin.x * Tile.SUBTILE_HEIGHT50) - (origin.y * Tile.SUBTILE_HEIGHT50);
|
||||
animation.draw(batch, x, y);
|
||||
}
|
||||
|
||||
public void setAngle(float rad) {
|
||||
if (angle != rad) {
|
||||
angle = rad;
|
||||
if (animation != null) animation.setDirection(getDirection());
|
||||
}
|
||||
}
|
||||
|
||||
public int getDirection() {
|
||||
int numDirs = animation.getNumDirections();
|
||||
return Direction.radiansToDirection(angle, numDirs);
|
||||
}
|
||||
|
||||
public GridPoint2 origin() {
|
||||
return origin;
|
||||
}
|
||||
|
||||
// TODO: Delete
|
||||
public void setOrigin(GridPoint2 origin) {
|
||||
this.origin = origin;
|
||||
}
|
||||
|
||||
public void move() {
|
||||
if (!mode.equalsIgnoreCase("WL")
|
||||
&& !mode.equalsIgnoreCase("RN")
|
||||
&& !mode.equalsIgnoreCase("TW")) {
|
||||
return;
|
||||
}
|
||||
|
||||
int x = Direction.getOffX(angle);
|
||||
int y = Direction.getOffY(angle);
|
||||
origin.add(x, y);
|
||||
}
|
||||
}
|
@ -1,353 +0,0 @@
|
||||
package gdx.diablo.entity3;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.GdxRuntimeException;
|
||||
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
|
||||
import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
import gdx.diablo.CharClass;
|
||||
import gdx.diablo.Diablo;
|
||||
import gdx.diablo.codec.COFD2;
|
||||
import gdx.diablo.codec.D2S;
|
||||
import gdx.diablo.codec.excel.Armor;
|
||||
import gdx.diablo.codec.excel.Weapons;
|
||||
import gdx.diablo.item.BodyLoc;
|
||||
import gdx.diablo.item.Item;
|
||||
|
||||
public class Player extends Entity implements Cloneable {
|
||||
@Override
|
||||
public Player clone() {
|
||||
try {
|
||||
return (Player) super.clone();
|
||||
} catch (CloneNotSupportedException t) {
|
||||
throw new GdxRuntimeException(t);
|
||||
}
|
||||
}
|
||||
|
||||
private static final String TAG = "Player";
|
||||
private static final boolean DEBUG = true;
|
||||
private static final boolean DEBUG_WCLASS = DEBUG && !true;
|
||||
|
||||
public enum Slot {
|
||||
HEAD, NECK, TORS, RARM, LARM, RRIN, LRIN, BELT, FEET, GLOV;
|
||||
|
||||
public BodyLoc toBodyLoc(boolean alternate) {
|
||||
return toBodyLoc(this, alternate);
|
||||
}
|
||||
|
||||
public static BodyLoc toBodyLoc(Slot slot, boolean alternate) {
|
||||
switch (slot) {
|
||||
case HEAD: return BodyLoc.HEAD;
|
||||
case NECK: return BodyLoc.NECK;
|
||||
case TORS: return BodyLoc.TORS;
|
||||
case RARM: return alternate ? BodyLoc.RARM2 : BodyLoc.RARM;
|
||||
case LARM: return alternate ? BodyLoc.LARM2 : BodyLoc.LARM;
|
||||
case RRIN: return BodyLoc.RRIN;
|
||||
case LRIN: return BodyLoc.LRIN;
|
||||
case BELT: return BodyLoc.BELT;
|
||||
case FEET: return BodyLoc.FEET;
|
||||
case GLOV: return BodyLoc.GLOV;
|
||||
default:
|
||||
throw new GdxRuntimeException("Invalid slot: " + slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
D2S d2s;
|
||||
boolean alternate;
|
||||
EnumMap<BodyLoc, Item> equipped = new EnumMap<>(BodyLoc.class);
|
||||
Array<Item> inventory = new Array<>();
|
||||
final Set<SlotListener> SLOT_LISTENERS = new CopyOnWriteArraySet<>();
|
||||
public Stats stats;
|
||||
|
||||
|
||||
public Player(String name, CharClass clazz) {
|
||||
super(Diablo.files.PlrType.get(clazz.id).Token, EntType.CHARS);
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public Player(D2S d2s) {
|
||||
super(Diablo.files.PlrType.get(d2s.charClass).Token, EntType.CHARS);
|
||||
this.d2s = d2s;
|
||||
this.stats = new Stats();
|
||||
equipped.putAll(d2s.items.equipped);
|
||||
inventory.addAll(d2s.items.inventory);
|
||||
setMode("TN");
|
||||
|
||||
for (Map.Entry<BodyLoc, Item> entry : equipped.entrySet()) {
|
||||
entry.getValue().load();
|
||||
//if (DEBUG_EQUIPPED) Gdx.app.debug(TAG, entry.getKey() + ": " + entry.getValue());
|
||||
}
|
||||
|
||||
for (Item item : inventory) {
|
||||
item.load();
|
||||
//if (DEBUG_INVENTORY) Gdx.app.debug(TAG, item.gridX + "," + item.gridY + ": " + item);
|
||||
}
|
||||
}
|
||||
|
||||
public Item getSlot(Slot slot) {
|
||||
BodyLoc loc = slot.toBodyLoc(alternate);
|
||||
return getSlot(loc);
|
||||
}
|
||||
|
||||
public Item getSlot(BodyLoc loc) {
|
||||
return equipped.get(loc);
|
||||
}
|
||||
|
||||
public Item setSlot(Slot slot, Item item) {
|
||||
Preconditions.checkState(item == null || getSlot(slot) == null, "Slot must be empty first!");
|
||||
BodyLoc loc = slot.toBodyLoc(alternate);
|
||||
return setSlot(loc, item);
|
||||
}
|
||||
|
||||
public Item setSlot(BodyLoc loc, Item item) {
|
||||
Item oldItem = equipped.put(loc, item);
|
||||
|
||||
//invalidate();
|
||||
//setArmType(slot, item.base.alternateGfx);
|
||||
int components = loc.components();
|
||||
if (components > 0) dirty |= components;
|
||||
updateWeaponClass();
|
||||
|
||||
notifySlotChanged(loc, oldItem, item);
|
||||
return oldItem;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Item getItem(Component component) {
|
||||
switch (component) {
|
||||
case HD: return getSlot(Slot.HEAD);
|
||||
case TR:
|
||||
case RA:
|
||||
case LA:
|
||||
case S1:
|
||||
case S2: return getSlot(Slot.TORS);
|
||||
// TODO: Shield/weapons?
|
||||
default: return super.getItem(component);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isAlternate() {
|
||||
return alternate;
|
||||
}
|
||||
|
||||
public void setAlternate(boolean b) {
|
||||
if (alternate != b) {
|
||||
alternate = b;
|
||||
updateWeaponClass();
|
||||
Item LH = getSlot(BodyLoc.LARM);
|
||||
Item RH = getSlot(BodyLoc.RARM);
|
||||
Item LH2 = getSlot(BodyLoc.LARM2);
|
||||
Item RH2 = getSlot(BodyLoc.RARM2);
|
||||
if (b) {
|
||||
notifyAlternate(LH2, RH2);
|
||||
} else {
|
||||
notifyAlternate(LH, RH);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected COFD2 getCOFs() {
|
||||
return Diablo.cofs.chars_cof;
|
||||
}
|
||||
|
||||
public void update() {
|
||||
updateWeaponClass();
|
||||
|
||||
Item head = getSlot(Slot.HEAD);
|
||||
setArmType(Component.HD, head != null ? head.base.alternateGfx : "LIT");
|
||||
|
||||
Item body = getSlot(Slot.TORS);
|
||||
if (body != null) {
|
||||
Armor.Entry armor = body.getBase();
|
||||
setArmType(Component.TR, Diablo.files.ArmType.get(armor.Torso).Token);
|
||||
setArmType(Component.LG, Diablo.files.ArmType.get(armor.Legs ).Token);
|
||||
setArmType(Component.RA, Diablo.files.ArmType.get(armor.rArm ).Token);
|
||||
setArmType(Component.LA, Diablo.files.ArmType.get(armor.lArm ).Token);
|
||||
setArmType(Component.S1, Diablo.files.ArmType.get(armor.lSPad).Token);
|
||||
setArmType(Component.S2, Diablo.files.ArmType.get(armor.rSPad).Token);
|
||||
} else {
|
||||
setArmType(Component.TR, DEFAULT_LAYER);
|
||||
setArmType(Component.LG, DEFAULT_LAYER);
|
||||
setArmType(Component.RA, DEFAULT_LAYER);
|
||||
setArmType(Component.LA, DEFAULT_LAYER);
|
||||
setArmType(Component.S1, DEFAULT_LAYER);
|
||||
setArmType(Component.S2, DEFAULT_LAYER);
|
||||
}
|
||||
|
||||
super.update();
|
||||
}
|
||||
|
||||
private void updateWeaponClass() {
|
||||
Item RH = null, LH = null, SH = null;
|
||||
Item rArm = getSlot(Slot.RARM);
|
||||
if (rArm != null) {
|
||||
if (rArm.type.is("weap")) {
|
||||
RH = rArm;
|
||||
} else if (rArm.type.is("shld")) {
|
||||
SH = rArm;
|
||||
}
|
||||
}
|
||||
|
||||
Item lArm = getSlot(Slot.LARM);
|
||||
if (lArm != null) {
|
||||
if (lArm.type.is("weap")) {
|
||||
LH = lArm;
|
||||
} else if (lArm.type.is("shld")) {
|
||||
SH = lArm;
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG_WCLASS) {
|
||||
Gdx.app.debug(TAG, "RH = " + RH);
|
||||
Gdx.app.debug(TAG, "LH = " + LH);
|
||||
Gdx.app.debug(TAG, "SH = " + SH);
|
||||
}
|
||||
|
||||
if (LH != null && RH != null) {
|
||||
Weapons.Entry LHEntry = LH.getBase();
|
||||
Weapons.Entry RHEntry = RH.getBase();
|
||||
if ( LHEntry.wclass.equals("1hs") && RHEntry.wclass.equals("1hs")) {
|
||||
setWeaponClass("1SS"); // Left Swing Right Swing
|
||||
} else if (LHEntry.wclass.equals("1hs") && RHEntry.wclass.equals("1ht")) {
|
||||
setWeaponClass("1ST"); // Left Swing Right Thrust
|
||||
} else if (LHEntry.wclass.equals("1ht") && RHEntry.wclass.equals("1hs")) {
|
||||
setWeaponClass("1JS"); // Left Jab Right Swing
|
||||
} else if (LHEntry.wclass.equals("1ht") && RHEntry.wclass.equals("1ht")) {
|
||||
setWeaponClass("1JT"); // Left Jab Right Thrust
|
||||
} else if (LH.type.is("miss") || RH.type.is("miss")) {
|
||||
setWeaponClass(LH.type.is("miss") ? LHEntry.wclass : RHEntry.wclass);
|
||||
} else if (LH.type.is("h2h") || RH.type.is("h2h")) {
|
||||
setWeaponClass("HT2"); // Two Hand-to-Hand
|
||||
} else {
|
||||
setWeaponClass("HTH");
|
||||
Gdx.app.error(TAG, String.format(
|
||||
"Unknown weapon combination: LH=%s RH=%s", LHEntry.wclass, RHEntry.wclass));
|
||||
}
|
||||
} else if (LH != null || RH != null) {
|
||||
RH = ObjectUtils.firstNonNull(RH, LH);
|
||||
LH = null;
|
||||
if (RH.type.is("bow")) {
|
||||
LH = RH;
|
||||
RH = null;
|
||||
Weapons.Entry LHEntry = LH.getBase();
|
||||
setWeaponClass(LHEntry.wclass);
|
||||
} else if (RH.type.is("weap")) { // make sure weap and not e.g. misl, might not be required
|
||||
Weapons.Entry RHEntry = RH.getBase();
|
||||
setWeaponClass(RHEntry.wclass);
|
||||
} else {
|
||||
setWeaponClass("HTH");
|
||||
}
|
||||
} else {
|
||||
setWeaponClass("HTH");
|
||||
}
|
||||
|
||||
setArmType(Component.RH, RH != null ? RH.base.alternateGfx : "");
|
||||
setArmType(Component.LH, LH != null ? LH.base.alternateGfx : "");
|
||||
setArmType(Component.SH, SH != null ? SH.base.alternateGfx : "");
|
||||
}
|
||||
|
||||
private void notifySlotChanged(BodyLoc bodyLoc, Item oldItem, Item item) {
|
||||
for (SlotListener l : SLOT_LISTENERS) l.onChanged(this, bodyLoc, oldItem, item);
|
||||
}
|
||||
|
||||
private void notifyAlternate(Item LH, Item RH) {
|
||||
for (SlotListener l : SLOT_LISTENERS) l.onAlternate(this, LH, RH);
|
||||
}
|
||||
|
||||
public boolean addSlotListener(SlotListener l) {
|
||||
boolean added = SLOT_LISTENERS.add(l);
|
||||
return added;
|
||||
}
|
||||
|
||||
public boolean containsSlotListener(Object o) {
|
||||
return o != null && SLOT_LISTENERS.contains(o);
|
||||
}
|
||||
|
||||
public boolean removeSlotListener(Object o) {
|
||||
return o != null && SLOT_LISTENERS.remove(o);
|
||||
}
|
||||
|
||||
public boolean clearSlotListeners() {
|
||||
boolean empty = SLOT_LISTENERS.isEmpty();
|
||||
SLOT_LISTENERS.clear();
|
||||
return !empty;
|
||||
}
|
||||
|
||||
public interface SlotListener {
|
||||
void onChanged(Player player, BodyLoc bodyLoc, Item oldItem, Item item);
|
||||
void onAlternate(Player player, Item LH, Item RH);
|
||||
}
|
||||
|
||||
public static class SlotAdapter implements SlotListener {
|
||||
@Override public void onChanged(Player player, BodyLoc bodyLoc, Item oldItem, Item item) {}
|
||||
@Override public void onAlternate(Player player, Item LH, Item RH) {}
|
||||
}
|
||||
|
||||
public Array<Item> getInventory() {
|
||||
return inventory;
|
||||
}
|
||||
|
||||
public class Stats {
|
||||
public int getClassId() {
|
||||
return d2s.charClass;
|
||||
}
|
||||
|
||||
public CharClass getCharClass() {
|
||||
return CharClass.get(d2s.charClass);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return d2s.name;
|
||||
}
|
||||
|
||||
public int getLevel() {
|
||||
return d2s.stats.level;
|
||||
}
|
||||
|
||||
public long getExperience() {
|
||||
return d2s.stats.xp;
|
||||
}
|
||||
|
||||
public int getStrength() {
|
||||
return d2s.stats.strength;
|
||||
}
|
||||
|
||||
public int getDexterity() {
|
||||
return d2s.stats.dexterity;
|
||||
}
|
||||
|
||||
public int getVitality() {
|
||||
return d2s.stats.vitality;
|
||||
}
|
||||
|
||||
public int getEnergy() {
|
||||
return d2s.stats.energy;
|
||||
}
|
||||
|
||||
public int getFireResistance() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getColdResistance() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getLightningResistance() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getPoisonResistance() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,589 +0,0 @@
|
||||
package gdx.diablo.map2;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.files.FileHandle;
|
||||
import com.badlogic.gdx.math.GridPoint2;
|
||||
import com.badlogic.gdx.utils.GdxRuntimeException;
|
||||
import com.badlogic.gdx.utils.IntMap;
|
||||
import com.badlogic.gdx.utils.StreamUtils;
|
||||
|
||||
import org.apache.commons.io.EndianUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Arrays;
|
||||
|
||||
import gdx.diablo.util.BufferUtils;
|
||||
|
||||
public class DS1 {
|
||||
private static final String TAG = "DS1";
|
||||
private static final boolean DEBUG = true;
|
||||
private static final boolean DEBUG_FILES = DEBUG && true;
|
||||
private static final boolean DEBUG_SIZES = DEBUG && true;
|
||||
private static final boolean DEBUG_LAYERS = DEBUG && true;
|
||||
private static final boolean DEBUG_CELLS = DEBUG && !true;
|
||||
private static final boolean DEBUG_OBJECTS = DEBUG && true;
|
||||
private static final boolean DEBUG_GROUPS = DEBUG && true;
|
||||
private static final boolean DEBUG_PATHS = DEBUG && true;
|
||||
private static final boolean DEBUG_STREAM = DEBUG && true;
|
||||
private static final boolean DEBUG_PROPS = DEBUG && true;
|
||||
|
||||
private static final int ACT_MAX = 5;
|
||||
private static final int DWORD = 4;
|
||||
|
||||
public static final int MAX_FLOOR_LAYERS = 2;
|
||||
public static final int MAX_SHADOW_LAYERS = 1;
|
||||
public static final int MAX_WALL_LAYERS = 4;
|
||||
|
||||
public static final int FLOOR_OFFSET = 0;
|
||||
public static final int SHADOW_OFFSET = FLOOR_OFFSET + MAX_FLOOR_LAYERS;
|
||||
public static final int WALL_OFFSET = SHADOW_OFFSET + MAX_SHADOW_LAYERS;
|
||||
public static final int MAX_LAYERS = WALL_OFFSET + MAX_WALL_LAYERS;
|
||||
|
||||
public static final int WALL_LAYER = 1;
|
||||
public static final int ORIENT_LAYER = 5;
|
||||
public static final int FLOOR_LAYER = 9;
|
||||
public static final int SHADOW_LAYER = 11;
|
||||
public static final int TAG_LAYER = 12;
|
||||
public static final int STREAM_LAYERS = 12;
|
||||
|
||||
public static final int WALL_LAYER_1 = WALL_LAYER;
|
||||
public static final int WALL_LAYER_2 = WALL_LAYER + 1;
|
||||
public static final int WALL_LAYER_3 = WALL_LAYER + 2;
|
||||
public static final int WALL_LAYER_4 = WALL_LAYER + 3;
|
||||
|
||||
public static final int ORIENT_LAYER_1 = ORIENT_LAYER;
|
||||
public static final int ORIENT_LAYER_2 = ORIENT_LAYER + 1;
|
||||
public static final int ORIENT_LAYER_3 = ORIENT_LAYER + 2;
|
||||
public static final int ORIENT_LAYER_4 = ORIENT_LAYER + 3;
|
||||
|
||||
public static final int FLOOR_LAYER_1 = FLOOR_LAYER;
|
||||
public static final int FLOOR_LAYER_2 = FLOOR_LAYER + 1;
|
||||
|
||||
private static final short ORIENTATION_TABLE[] = {
|
||||
0x00, 0x01, 0x02, 0x01, 0x02, 0x03, 0x03, 0x05, 0x05, 0x06,
|
||||
0x06, 0x07, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
|
||||
0x0F, 0x10, 0x11, 0x12, 0x14
|
||||
};
|
||||
|
||||
int version;
|
||||
int width;
|
||||
int height;
|
||||
int act;
|
||||
int tagType;
|
||||
|
||||
int numFiles;
|
||||
String files[];
|
||||
|
||||
int numWalls;
|
||||
int numFloors;
|
||||
int numTags;
|
||||
int numShadows;
|
||||
|
||||
int numLayers;
|
||||
int layerStream[];
|
||||
|
||||
int wallLine, wallLen;
|
||||
Cell walls[];
|
||||
|
||||
int floorLine, floorLen;
|
||||
Cell floors[];
|
||||
|
||||
int shadowLine, shadowLen;
|
||||
Cell shadows[];
|
||||
|
||||
int tagLine, tagLen;
|
||||
int tags[];
|
||||
|
||||
int numObjects;
|
||||
Object objects[];
|
||||
|
||||
int numGroups;
|
||||
Group groups[];
|
||||
|
||||
int numPaths;
|
||||
Path paths[];
|
||||
|
||||
IntMap<GridPoint2> specials;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this)
|
||||
.append("version", version)
|
||||
.append("width", width)
|
||||
.append("height", height)
|
||||
.append("act", act)
|
||||
.append("tagType", tagType)
|
||||
.append("numFiles", numFiles)
|
||||
.append("numWalls", numWalls)
|
||||
.append("numFloors", numFloors)
|
||||
.append("numTags", numTags)
|
||||
.append("numShadows", numShadows)
|
||||
.append("layerStream", Arrays.toString(Arrays.copyOf(layerStream, numLayers)))
|
||||
.append("floorLine", floorLine)
|
||||
.append("floorLen", floorLen)
|
||||
.append("shadowLine", shadowLine)
|
||||
.append("shadowLen", shadowLen)
|
||||
.append("tagLine", tagLine)
|
||||
.append("tagLen", tagLen)
|
||||
.append("wallLine", wallLine)
|
||||
.append("wallLen", wallLen)
|
||||
.append("numObjects", numObjects)
|
||||
.append("numGroups", numGroups)
|
||||
.append("numPaths", numPaths)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public GridPoint2 find(int id) {
|
||||
return specials.get(id);
|
||||
}
|
||||
|
||||
public GridPoint2 find(int orientation, int mainIndex, int subIndex) {
|
||||
int id = DT1.Tile.Index.create(orientation, mainIndex, subIndex);
|
||||
return find(id);
|
||||
}
|
||||
|
||||
public static DS1 loadFromFile(FileHandle handle) {
|
||||
return loadFromStream(handle.read());
|
||||
}
|
||||
|
||||
public static DS1 loadFromStream(InputStream in) {
|
||||
try {
|
||||
DS1 ds1 = new DS1().read(in);
|
||||
if (DEBUG) Gdx.app.debug(TAG, ds1.toString());
|
||||
if (ds1.version < 9 || 13 < ds1.version) {
|
||||
// FIXME: version 9 <= 13 causes crash here /w 4B remaining, why?
|
||||
assert in.available() == 0 : in.available() + "B available!";
|
||||
} else if (DEBUG_STREAM && in.available() > 0) {
|
||||
Gdx.app.error(TAG, in.available() + "B still available in stream!");
|
||||
}
|
||||
|
||||
return ds1;
|
||||
} catch (Throwable t) {
|
||||
throw new GdxRuntimeException("Couldn't read DS1.", t);
|
||||
} finally {
|
||||
StreamUtils.closeQuietly(in);
|
||||
}
|
||||
}
|
||||
|
||||
private DS1 read(InputStream in) throws IOException {
|
||||
version = EndianUtils.readSwappedInteger(in);
|
||||
width = EndianUtils.readSwappedInteger(in) + 1;
|
||||
height = EndianUtils.readSwappedInteger(in) + 1;
|
||||
act = version < 8 ? 1 : Math.min(EndianUtils.readSwappedInteger(in) + 1, ACT_MAX);
|
||||
tagType = version < 10 ? 0 : EndianUtils.readSwappedInteger(in);
|
||||
numFiles = version < 3 ? 0 : EndianUtils.readSwappedInteger(in);
|
||||
files = numFiles == 0 ? ArrayUtils.EMPTY_STRING_ARRAY : new String[numFiles];
|
||||
for (int i = 0; i < numFiles; i++) {
|
||||
files[i] = BufferUtils.readString(in);
|
||||
if (DEBUG_FILES) Gdx.app.debug(TAG, "file[" + i + "] = " + files[i]);
|
||||
}
|
||||
if (9 <= version && version <= 13) IOUtils.skipFully(in, 2 * DWORD);
|
||||
if (version < 4) {
|
||||
numWalls = 1;
|
||||
numFloors = 1;
|
||||
numTags = 1;
|
||||
numShadows = 1;
|
||||
} else {
|
||||
numWalls = EndianUtils.readSwappedInteger(in);
|
||||
numFloors = version < 16 ? 1 : EndianUtils.readSwappedInteger(in);
|
||||
numTags = (tagType == 1 || tagType == 2) ? 1 : 0;
|
||||
numShadows = 1;
|
||||
}
|
||||
|
||||
if (DEBUG_SIZES) Gdx.app.debug(TAG, String.format("layers: (2 * %d walls) + %d floors + %d shadow + %d tag", numWalls, numFloors, numShadows, numTags));
|
||||
|
||||
layerStream = new int[STREAM_LAYERS];
|
||||
if (version < 4) {
|
||||
numLayers = 5;
|
||||
layerStream[0] = WALL_LAYER;
|
||||
layerStream[1] = FLOOR_LAYER;
|
||||
layerStream[2] = ORIENT_LAYER;
|
||||
layerStream[3] = TAG_LAYER;
|
||||
layerStream[4] = SHADOW_LAYER;
|
||||
} else {
|
||||
numLayers = 0;
|
||||
for (int i = 0; i < numWalls; i++) {
|
||||
layerStream[numLayers++] = WALL_LAYER + i;
|
||||
layerStream[numLayers++] = ORIENT_LAYER + i;
|
||||
}
|
||||
for (int i = 0; i < numFloors; i++) {
|
||||
layerStream[numLayers++] = FLOOR_LAYER + i;
|
||||
}
|
||||
if (numShadows > 0) {
|
||||
layerStream[numLayers++] = SHADOW_LAYER;
|
||||
}
|
||||
if (numTags > 0) {
|
||||
layerStream[numLayers++] = TAG_LAYER;
|
||||
}
|
||||
}
|
||||
|
||||
floorLine = width * numFloors;
|
||||
floorLen = floorLine * height;
|
||||
floors = new Cell[floorLen];
|
||||
int floorOffset[] = new int[numFloors];
|
||||
for (int i = 0; i < numFloors; i++) {
|
||||
floorOffset[i] = i;
|
||||
}
|
||||
|
||||
shadowLine = width * numShadows;
|
||||
shadowLen = shadowLine * height;
|
||||
shadows = new Cell[shadowLen];
|
||||
int shadowOffset[] = new int[numShadows];
|
||||
for (int i = 0; i < numShadows; i++) {
|
||||
shadowOffset[i] = i;
|
||||
}
|
||||
|
||||
tagLine = width * numTags;
|
||||
tagLen = tagLine * height;
|
||||
tags = new int[tagLen];
|
||||
int tagOffset[] = new int[numTags];
|
||||
for (int i = 0; i < numTags; i++) {
|
||||
tagOffset[i] = i;
|
||||
}
|
||||
|
||||
wallLine = width * numWalls;
|
||||
wallLen = wallLine * height;
|
||||
walls = new Cell[wallLen];
|
||||
int wallOffset[] = new int[numWalls], orientationOffset[] = new int[numWalls];
|
||||
for (int i = 0; i < numWalls; i++) {
|
||||
wallOffset[i] = orientationOffset[i] = i;
|
||||
}
|
||||
|
||||
if (DEBUG_LAYERS) Gdx.app.debug(TAG, "floorLine=" + floorLine + "; floorLen=" + floorLen);
|
||||
if (DEBUG_LAYERS) Gdx.app.debug(TAG, "shadowLine=" + shadowLine + "; shadowLen=" + shadowLen);
|
||||
if (DEBUG_LAYERS) Gdx.app.debug(TAG, "tagLine=" + tagLine + "; tagLen=" + tagLen);
|
||||
if (DEBUG_LAYERS) Gdx.app.debug(TAG, "wallLine=" + wallLine + "; wallLen=" + wallLen);
|
||||
if (DEBUG_LAYERS) Gdx.app.debug(TAG, "layerStream=" + Arrays.toString(Arrays.copyOf(layerStream, numLayers)));
|
||||
|
||||
specials = new IntMap<>();
|
||||
for (int l = 0, layer, i, id; l < numLayers; l++) {
|
||||
layer = layerStream[l];
|
||||
for (int y = 0; y < height; y++) {
|
||||
for (int x = 0; x < width; x++) {
|
||||
switch (layer) {
|
||||
// wall
|
||||
case WALL_LAYER_1: case WALL_LAYER_2: case WALL_LAYER_3: case WALL_LAYER_4:
|
||||
i = layer - WALL_LAYER;
|
||||
id = wallOffset[i];
|
||||
assert walls[id] == null;
|
||||
walls[id] = new Cell().read(in);
|
||||
wallOffset[i] += numWalls;
|
||||
break;
|
||||
|
||||
// orientation
|
||||
case ORIENT_LAYER_1: case ORIENT_LAYER_2: case ORIENT_LAYER_3: case ORIENT_LAYER_4:
|
||||
i = layer - ORIENT_LAYER;
|
||||
id = orientationOffset[i];
|
||||
Cell wall = walls[id];
|
||||
assert wall != null;
|
||||
int j = EndianUtils.readSwappedInteger(in);
|
||||
wall.setOrientation(version < 7 ? ORIENTATION_TABLE[j] : j);
|
||||
orientationOffset[i] += numWalls;
|
||||
|
||||
if (!Orientation.isSpecial(wall.orientation)) {
|
||||
break;
|
||||
}
|
||||
|
||||
specials.put(wall.id, new GridPoint2(x, y));
|
||||
if (DEBUG_PROPS) {
|
||||
int mainIndex = (wall.value & 0x03F00000) >>> 20;
|
||||
int subIndex = (wall.value & 0x0000FF00) >>> 8;
|
||||
int first = (wall.value & 0xFC000000) >>> 26;
|
||||
int second = (wall.value & 0x000F0000) >>> 16;
|
||||
int third = (wall.value & 0x000000FF);
|
||||
Gdx.app.debug(TAG, String.format("%d (%2d,%2d) %08X %2d,%2d,%2d %02X %02X %X %02X %02X",
|
||||
l, x, y, wall.value,
|
||||
mainIndex, wall.orientation, subIndex,
|
||||
first, mainIndex, second, subIndex, third));
|
||||
}
|
||||
break;
|
||||
|
||||
// floor
|
||||
case FLOOR_LAYER_1: case FLOOR_LAYER_2:
|
||||
i = layer - FLOOR_LAYER;
|
||||
id = floorOffset[i];
|
||||
assert floors[id] == null;
|
||||
floors[id] = new Cell().read(in);
|
||||
floorOffset[i] += numFloors;
|
||||
break;
|
||||
|
||||
// shadow
|
||||
case SHADOW_LAYER:
|
||||
i = layer - SHADOW_LAYER;
|
||||
id = shadowOffset[i];
|
||||
assert shadows[id] == null;
|
||||
shadows[id] = new Cell().read(in);
|
||||
shadowOffset[i] += numShadows;
|
||||
break;
|
||||
|
||||
// tag
|
||||
case TAG_LAYER:
|
||||
i = layer - TAG_LAYER;
|
||||
id = tagOffset[i];
|
||||
tags[id] = EndianUtils.readSwappedInteger(in);
|
||||
tagOffset[i] += numTags;
|
||||
break;
|
||||
|
||||
// error
|
||||
default:
|
||||
Gdx.app.error(TAG, "Unknown layer: " + layer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG_CELLS) {
|
||||
for (int i = 0; i < wallLen; i++) Gdx.app.debug(TAG, "walls[" + i + "]=" + walls[i].toString());
|
||||
for (int i = 0; i < floorLen; i++) Gdx.app.debug(TAG, "floors[" + i + "]=" + floors[i].toString());
|
||||
for (int i = 0; i < shadowLen; i++) Gdx.app.debug(TAG, "shadows[" + i + "]=" + shadows[i].toString());
|
||||
Gdx.app.debug(TAG, "tags=" + Arrays.toString(tags));
|
||||
}
|
||||
|
||||
int maxSubtileWidth = width * 5;
|
||||
int maxSubtileHeight = height * 5;
|
||||
|
||||
numObjects = version < 2 ? 0 : EndianUtils.readSwappedInteger(in);
|
||||
objects = numObjects == 0 ? Object.EMPTY_OBJECT_ARRAY : new Object[numObjects];
|
||||
for (int i = 0; i < numObjects; i++) {
|
||||
try {
|
||||
Object object = objects[i] = new Object().read(version, in);
|
||||
if (DEBUG_OBJECTS) Gdx.app.debug(TAG, object.toString());
|
||||
if (object.x < 0 || maxSubtileWidth <= object.x
|
||||
|| object.y < 0 || maxSubtileHeight <= object.y) {
|
||||
Gdx.app.error(TAG, "Object out of DS1 bounds: " + object);
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
// Don't care, invalid object, skip it. Log it for posterity.
|
||||
Gdx.app.error(TAG, t.getMessage(), t);
|
||||
}
|
||||
}
|
||||
|
||||
if (version >= 12 && (tagType == 1 || tagType == 2)) {
|
||||
if (version >= 18) IOUtils.skip(in, DWORD);
|
||||
numGroups = EndianUtils.readSwappedInteger(in);
|
||||
groups = numGroups == 0 ? Group.EMPTY_GROUP_ARRAY : new Group[numGroups];
|
||||
for (int i = 0; i < numGroups; i++) {
|
||||
groups[i] = new Group().read(version, in);
|
||||
if (DEBUG_GROUPS) Gdx.app.debug(TAG, groups[i].toString());
|
||||
}
|
||||
} else {
|
||||
numGroups = 0;
|
||||
groups = Group.EMPTY_GROUP_ARRAY;
|
||||
}
|
||||
|
||||
if (version >= 14 && in.available() >= DWORD) {
|
||||
numPaths = EndianUtils.readSwappedInteger(in);
|
||||
paths = numPaths == 0 ? Path.EMPTY_PATH_ARRAY : new Path[numPaths];
|
||||
for (int i = 0; i < numPaths; i++) {
|
||||
Path path = paths[i] = new Path().read(version, objects, in);
|
||||
if (DEBUG_PATHS) Gdx.app.debug(TAG, path.toString());
|
||||
}
|
||||
} else {
|
||||
numPaths = 0;
|
||||
paths = Path.EMPTY_PATH_ARRAY;
|
||||
}
|
||||
|
||||
width -= 1;
|
||||
height -= 1;
|
||||
return this;
|
||||
}
|
||||
|
||||
static class Cell {
|
||||
// 0x03F00000
|
||||
private static final int MAIN_INDEX_OFFSET = 20;
|
||||
private static final int MAIN_INDEX_BITS = 0x3F;
|
||||
|
||||
// 0x0000FF00
|
||||
private static final int SUB_INDEX_OFFSET = 8;
|
||||
private static final int SUB_INDEX_BITS = 0xFF;
|
||||
|
||||
public static final int MASK_MAIN_INDEX = MAIN_INDEX_BITS << MAIN_INDEX_OFFSET;
|
||||
public static final int SUB_MAIN_INDEX = SUB_INDEX_BITS << SUB_INDEX_OFFSET;
|
||||
public static final int MASK_UNWALKABLE = 0x00020000;
|
||||
|
||||
int id;
|
||||
int value;
|
||||
|
||||
short mainIndex;
|
||||
short subIndex;
|
||||
short orientation;
|
||||
|
||||
Cell read(InputStream in) throws IOException {
|
||||
value = EndianUtils.readSwappedInteger(in);
|
||||
mainIndex = (short) ((value >>> MAIN_INDEX_OFFSET) & MAIN_INDEX_BITS);
|
||||
subIndex = (short) ((value >>> SUB_INDEX_OFFSET) & SUB_INDEX_BITS);
|
||||
orientation = Orientation.FLOOR;
|
||||
id = DT1.Tile.Index.create(orientation, mainIndex, subIndex);
|
||||
return updateIndex();
|
||||
}
|
||||
|
||||
void setOrientation(int orientation) {
|
||||
this.orientation = (short) orientation;
|
||||
updateIndex();
|
||||
}
|
||||
|
||||
Cell updateIndex() {
|
||||
id = DT1.Tile.Index.create(orientation, mainIndex, subIndex);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this)
|
||||
.append("id", Integer.toHexString(id))
|
||||
.append("value", Integer.toHexString(value))
|
||||
.append("mainIndex", mainIndex)
|
||||
.append("subIndex", subIndex)
|
||||
.append("orientation", orientation)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
public static class Object {
|
||||
public static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
|
||||
|
||||
public static final int DYNAMIC_TYPE = 1;
|
||||
public static final int STATIC_TYPE = 2;
|
||||
|
||||
int type;
|
||||
int id;
|
||||
int x;
|
||||
int y;
|
||||
int ds1Flags;
|
||||
|
||||
Object read(int version, InputStream in) throws IOException {
|
||||
type = EndianUtils.readSwappedInteger(in);
|
||||
id = EndianUtils.readSwappedInteger(in);
|
||||
x = EndianUtils.readSwappedInteger(in);
|
||||
y = EndianUtils.readSwappedInteger(in);
|
||||
ds1Flags = version < 6 ? 0 : EndianUtils.readSwappedInteger(in);
|
||||
return this;
|
||||
}
|
||||
|
||||
String getType() {
|
||||
switch (type) {
|
||||
case DYNAMIC_TYPE: return "DYNAMIC_TYPE";
|
||||
case STATIC_TYPE: return "STATIC_TYPE";
|
||||
default: return Integer.toString(type);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this)
|
||||
.append("type", getType())
|
||||
.append("id", id)
|
||||
.append("x", x)
|
||||
.append("y", y)
|
||||
.append("ds1Flags", "0x" + Integer.toHexString(ds1Flags))
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
static class Group {
|
||||
public static final Group[] EMPTY_GROUP_ARRAY = new Group[0];
|
||||
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
int unk;
|
||||
|
||||
Group read(int version, InputStream in) throws IOException {
|
||||
if (in.available() >= DWORD) x = EndianUtils.readSwappedInteger(in);
|
||||
if (in.available() >= DWORD) y = EndianUtils.readSwappedInteger(in);
|
||||
if (in.available() >= DWORD) width = EndianUtils.readSwappedInteger(in);
|
||||
if (in.available() >= DWORD) height = EndianUtils.readSwappedInteger(in);
|
||||
if (version >= 13) {
|
||||
if (in.available() >= DWORD) unk = EndianUtils.readSwappedInteger(in);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this)
|
||||
.append("x", x)
|
||||
.append("y", y)
|
||||
.append("width", width)
|
||||
.append("height", height)
|
||||
.append("unk", unk)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
public static class Path {
|
||||
public static final Path[] EMPTY_PATH_ARRAY = new Path[0];
|
||||
|
||||
int numPoints;
|
||||
Point points[];
|
||||
|
||||
int x;
|
||||
int y;
|
||||
|
||||
Path read(int version, Object[] objects, InputStream in) throws IOException {
|
||||
numPoints = EndianUtils.readSwappedInteger(in);
|
||||
points = new Point[numPoints];
|
||||
x = EndianUtils.readSwappedInteger(in);
|
||||
y = EndianUtils.readSwappedInteger(in);
|
||||
|
||||
Object object = null;
|
||||
for (int i = 0; i < objects.length; i++) {
|
||||
Object tmp = objects[i];
|
||||
if (tmp == null) continue;
|
||||
if (tmp.x != x || tmp.y != y) continue;
|
||||
if (object != null) Gdx.app.error(TAG, "More than one object is located at path position: " + this);
|
||||
object = tmp;
|
||||
}
|
||||
|
||||
if (object == null) {
|
||||
Gdx.app.error(TAG, "No object associated with path: " + this);
|
||||
int skip = version >= 15 ? 12 : 8;
|
||||
for (int p = 0; p < numPoints; p++) {
|
||||
in.skip(skip);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
for (int p = 0; p < numPoints; p++) points[p] = new Point().read(version, in);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this)
|
||||
.append("x", x)
|
||||
.append("y", y)
|
||||
.append("numPoints", numPoints)
|
||||
.append("points", Arrays.toString(points))
|
||||
.build();
|
||||
}
|
||||
|
||||
static class Point {
|
||||
int x;
|
||||
int y;
|
||||
int action;
|
||||
|
||||
Point read(int version, InputStream in) throws IOException {
|
||||
x = EndianUtils.readSwappedInteger(in);
|
||||
y = EndianUtils.readSwappedInteger(in);
|
||||
action = version < 15 ? 1 : EndianUtils.readSwappedInteger(in);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this)
|
||||
.append("x", x)
|
||||
.append("y", y)
|
||||
.append("action", action)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
package gdx.diablo.map2;
|
||||
|
||||
import com.badlogic.gdx.assets.AssetDescriptor;
|
||||
import com.badlogic.gdx.assets.AssetLoaderParameters;
|
||||
import com.badlogic.gdx.assets.AssetManager;
|
||||
import com.badlogic.gdx.assets.loaders.AsynchronousAssetLoader;
|
||||
import com.badlogic.gdx.assets.loaders.FileHandleResolver;
|
||||
import com.badlogic.gdx.files.FileHandle;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
|
||||
public class DS1Loader extends AsynchronousAssetLoader<DS1, DS1Loader.DS1LoaderParameters> {
|
||||
|
||||
DS1 ds1;
|
||||
|
||||
public DS1Loader(FileHandleResolver resolver) {
|
||||
super(resolver);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadAsync(AssetManager assets, String fileName, FileHandle file, DS1LoaderParameters params) {
|
||||
ds1 = DS1.loadFromStream(file.read());
|
||||
}
|
||||
|
||||
@Override
|
||||
public DS1 loadSync(AssetManager assets, String fileName, FileHandle file, DS1LoaderParameters params) {
|
||||
DS1 ds1 = this.ds1;
|
||||
if (ds1 == null) {
|
||||
ds1 = DS1.loadFromStream(file.read());
|
||||
} else {
|
||||
this.ds1 = null;
|
||||
}
|
||||
|
||||
return ds1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Array<AssetDescriptor> getDependencies(String fileName, FileHandle file, DS1LoaderParameters params) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static class DS1LoaderParameters extends AssetLoaderParameters<DS1> {}
|
||||
|
||||
}
|
@ -1,501 +0,0 @@
|
||||
package gdx.diablo.map2;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.files.FileHandle;
|
||||
import com.badlogic.gdx.graphics.Pixmap;
|
||||
import com.badlogic.gdx.graphics.Texture;
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||
import com.badlogic.gdx.graphics.glutils.PixmapTextureData;
|
||||
import com.badlogic.gdx.utils.Disposable;
|
||||
import com.badlogic.gdx.utils.GdxRuntimeException;
|
||||
import com.badlogic.gdx.utils.StreamUtils;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.Arrays;
|
||||
|
||||
import gdx.diablo.Diablo;
|
||||
import gdx.diablo.codec.Palette;
|
||||
import gdx.diablo.graphics.PaletteIndexedPixmap;
|
||||
import gdx.diablo.util.BufferUtils;
|
||||
|
||||
// TODO: In production, skip unused data (zeros/unknowns)
|
||||
public class DT1 implements Disposable {
|
||||
private static final String TAG = "DT1";
|
||||
private static final boolean DEBUG = true;
|
||||
private static final boolean DEBUG_TILE_HEADERS = DEBUG && !true;
|
||||
private static final boolean DEBUG_BLOCK_HEADERS = DEBUG && !true;
|
||||
|
||||
private static final int X_JUMP[] = { 14, 12, 10, 8, 6, 4, 2, 0, 2, 4, 6, 8, 10, 12, 14 };
|
||||
private static final int PIXEL_WIDTH[] = { 4, 8, 12, 16, 20, 24, 28, 32, 28, 24, 20, 16, 12, 8, 4 };
|
||||
|
||||
String fileName;
|
||||
Header header;
|
||||
Tile tiles[];
|
||||
Texture textures[];
|
||||
|
||||
private DT1(String fileName, Header header, Tile[] tiles) {
|
||||
this.fileName = fileName;
|
||||
this.header = header;
|
||||
this.tiles = tiles;
|
||||
Diablo.dt1s.add(this);
|
||||
}
|
||||
|
||||
public int getVersion1() {
|
||||
return header.version1;
|
||||
}
|
||||
|
||||
public int getVersion2() {
|
||||
return header.version2;
|
||||
}
|
||||
|
||||
public int getNumTiles() {
|
||||
return header.numTiles;
|
||||
}
|
||||
|
||||
public Tile getTile(int i) {
|
||||
return tiles[i];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
if (textures == null) return;
|
||||
for (Texture texture : textures) texture.dispose();
|
||||
Diablo.dt1s.remove(this);
|
||||
}
|
||||
|
||||
public TextureRegion getTexture(int i) {
|
||||
return new TextureRegion(textures[i]);
|
||||
}
|
||||
|
||||
public void prepareTextures() {
|
||||
Preconditions.checkState(textures == null, "textures have already been prepared");
|
||||
textures = new Texture[header.numTiles];
|
||||
for (int i = 0; i < header.numTiles; i++) {
|
||||
Texture texture = new Texture(new PixmapTextureData(tiles[i].pixmap, null, false, false, false));
|
||||
//texture.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
|
||||
texture.setWrap(Texture.TextureWrap.ClampToEdge, Texture.TextureWrap.ClampToEdge);
|
||||
textures[i] = tiles[i].texture = texture;
|
||||
}
|
||||
}
|
||||
|
||||
public static DT1 loadFromFile(FileHandle handle) {
|
||||
return loadFromStream(handle.path(), handle.read());
|
||||
}
|
||||
|
||||
public static DT1 loadFromStream(String fileName, InputStream in) {
|
||||
try {
|
||||
Header header = new Header(in);
|
||||
if (DEBUG) Gdx.app.debug(TAG, header.toString());
|
||||
|
||||
if (header.version1 != 0x7)
|
||||
throw new GdxRuntimeException("Unknown version1: " + header.version1);
|
||||
if (header.version2 != 0x6)
|
||||
throw new GdxRuntimeException("Unknown version2: " + header.version2);
|
||||
|
||||
Tile[] tiles = new Tile[header.numTiles];
|
||||
for (int i = 0; i < header.numTiles; i++) {
|
||||
Tile tile = tiles[i] = new Tile(in);
|
||||
if (DEBUG_TILE_HEADERS) Gdx.app.debug(TAG, tile.toString());
|
||||
}
|
||||
|
||||
for (Tile tile : tiles) {
|
||||
Block[] blockHeaders = tile.blocks = new Block[tile.numBlocks];
|
||||
for (int i = 0; i < tile.numBlocks; i++) {
|
||||
blockHeaders[i] = new Block(in);
|
||||
if (DEBUG_BLOCK_HEADERS) Gdx.app.debug(TAG, blockHeaders[i].toString());
|
||||
}
|
||||
|
||||
for (Block blockHeader : blockHeaders) {
|
||||
blockHeader.colormap = IOUtils.readFully(in, blockHeader.length);
|
||||
}
|
||||
|
||||
tile.createPixmap();
|
||||
}
|
||||
|
||||
assert in.available() == 0;
|
||||
return new DT1(fileName, header, tiles);
|
||||
} catch (Throwable t) {
|
||||
throw new GdxRuntimeException("Couldn't read DT1", t);
|
||||
} finally {
|
||||
StreamUtils.closeQuietly(in);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean allZeros(byte[] zeros) {
|
||||
for (byte b : zeros) {
|
||||
if (b != 0) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static class Header {
|
||||
static final int SIZE = 276;
|
||||
|
||||
int version1;
|
||||
int version2;
|
||||
byte zeros[];
|
||||
int numTiles;
|
||||
int tileOffset;
|
||||
|
||||
Header(InputStream in) throws IOException {
|
||||
ByteBuffer buffer = ByteBuffer.wrap(IOUtils.readFully(in, SIZE)).order(ByteOrder.LITTLE_ENDIAN);
|
||||
version1 = buffer.getInt();
|
||||
version2 = buffer.getInt();
|
||||
zeros = BufferUtils.readBytes(buffer, 260);
|
||||
numTiles = buffer.getInt();
|
||||
tileOffset = buffer.getInt();
|
||||
assert !buffer.hasRemaining();
|
||||
assert allZeros(zeros) : "Expected 260 zeros, got: " + Arrays.toString(zeros);
|
||||
assert tileOffset == SIZE : "Expected first tile header to be located at 276: " + tileOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this)
|
||||
.append("version1", version1)
|
||||
.append("version2", version2)
|
||||
//.append("zeros", Arrays.toString(zeros))
|
||||
.append("numTiles", numTiles)
|
||||
.append("tileOffset", "0x" + Integer.toHexString(tileOffset))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public static class Tile {
|
||||
static final int SIZE = 96;
|
||||
|
||||
public static final int WIDTH = 160;
|
||||
public static final int HEIGHT = 80;
|
||||
|
||||
public static final int SUBTILE_SIZE = 5;
|
||||
public static final int NUM_SUBTILES = SUBTILE_SIZE * SUBTILE_SIZE;
|
||||
|
||||
public static final int SUBTILE_WIDTH = WIDTH / SUBTILE_SIZE;
|
||||
public static final int SUBTILE_HEIGHT = HEIGHT / SUBTILE_SIZE;
|
||||
|
||||
public static final int[][] SUBTILE_INDEX/* = {
|
||||
{0, 5, 10, 15, 20},
|
||||
{1, 6, 11, 16, 21},
|
||||
{2, 7, 12, 17, 22},
|
||||
{3, 8, 13, 18, 23},
|
||||
{4, 9, 14, 19, 24},
|
||||
}*/;
|
||||
static {
|
||||
SUBTILE_INDEX = new int[SUBTILE_SIZE][SUBTILE_SIZE];
|
||||
for (int y = 0, i = 0; y < SUBTILE_SIZE; y++) {
|
||||
for (int x = 0; x < SUBTILE_SIZE; x++, i++) {
|
||||
SUBTILE_INDEX[x][y] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final int[][] SUBTILE_OFFSET/* = {
|
||||
{64, 64}, {80, 56}, {96, 48}, {112, 40}, {128, 32},
|
||||
{48, 56}, {64, 48}, {80, 40}, { 96, 32}, {112, 24},
|
||||
{32, 48}, {48, 40}, {64, 32}, { 80, 24}, { 96, 16},
|
||||
{16, 40}, {32, 32}, {48, 24}, { 64, 16}, { 80, 8},
|
||||
{ 0, 32}, {16, 24}, {32, 16}, { 48, 8}, { 64, 0},
|
||||
}*/;
|
||||
static {
|
||||
SUBTILE_OFFSET = new int[NUM_SUBTILES][2];
|
||||
final int halfSubtileWidth = SUBTILE_WIDTH / 2;
|
||||
final int halfSubtileHeight = SUBTILE_HEIGHT / 2;
|
||||
for (int y = 0, i = 0; y < SUBTILE_SIZE; y++) {
|
||||
int px = (WIDTH / 2) - halfSubtileWidth - (y * halfSubtileWidth);
|
||||
int py = HEIGHT - SUBTILE_HEIGHT - (y * halfSubtileHeight);
|
||||
for (int x = 0; x < SUBTILE_SIZE; x++, i++) {
|
||||
SUBTILE_OFFSET[i][0] = px;
|
||||
SUBTILE_OFFSET[i][1] = py;
|
||||
px += halfSubtileWidth;
|
||||
py -= halfSubtileHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static final int FLAG_BLOCK_WALK = 1 << 0;
|
||||
public static final int FLAG_BLOCK_LIGHT_LOS = 1 << 1;
|
||||
public static final int FLAG_BLOCK_JUMP = 1 << 2;
|
||||
public static final int FLAG_BLOCK_PLAYER_WALK = 1 << 3;
|
||||
public static final int FLAG_BLOCK_UNKNOWN1 = 1 << 4;
|
||||
public static final int FLAG_BLOCK_LIGHT = 1 << 5;
|
||||
public static final int FLAG_BLOCK_UNKNOWN2 = 1 << 6;
|
||||
public static final int FLAG_BLOCK_UNKNOWN3 = 1 << 7;
|
||||
|
||||
public int direction;
|
||||
public short roofHeight;
|
||||
public byte soundIndex;
|
||||
public byte animated;
|
||||
public int height;
|
||||
public int width;
|
||||
public byte zeros1[];
|
||||
public int orientation;
|
||||
public int mainIndex;
|
||||
public int subIndex;
|
||||
public int rarity; // frame index if animated
|
||||
public byte unknown[];
|
||||
public byte tileFlags[];
|
||||
public byte zeros2[];
|
||||
public int blockHeadersPointer;
|
||||
public int blockDataLength;
|
||||
public int numBlocks;
|
||||
public byte zeros3[];
|
||||
|
||||
Block blocks[];
|
||||
Pixmap pixmap;
|
||||
Texture texture;
|
||||
int id;
|
||||
|
||||
/**
|
||||
* zeros3 is not all zeros all of the time. This might correlate with unknown. I need to figure
|
||||
* out what these variables mean, I'm fairly certain zeros3 is 3 ints, or at least the second
|
||||
* 4 bytes are used somewhere.
|
||||
*
|
||||
* data\global\tiles\expansion\Town\shrine.dt1
|
||||
* data\global\tiles\expansion\Town\trees.dt1
|
||||
*
|
||||
* unknown in above is same F6 62 FF 00 (16737014)
|
||||
* but zeros3 is different:
|
||||
* 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
* 00 00 00 00 6C B0 08 0B 00 00 00 00
|
||||
*
|
||||
* data\global\tiles\expansion\Town\tent.dt1
|
||||
* F3 65 FF 00 (16737779)
|
||||
* 00 00 00 00 4C 00 37 0B 00 00 00 00
|
||||
*/
|
||||
Tile(InputStream in) throws IOException {
|
||||
ByteBuffer buffer = ByteBuffer.wrap(IOUtils.readFully(in, SIZE)).order(ByteOrder.LITTLE_ENDIAN);
|
||||
direction = buffer.getInt();
|
||||
roofHeight = buffer.getShort();
|
||||
soundIndex = buffer.get();
|
||||
animated = buffer.get();
|
||||
height = buffer.getInt();
|
||||
width = buffer.getInt();
|
||||
zeros1 = BufferUtils.readBytes(buffer, 4);
|
||||
orientation = buffer.getInt();
|
||||
mainIndex = buffer.getInt();
|
||||
subIndex = buffer.getInt();
|
||||
rarity = buffer.getInt();
|
||||
unknown = BufferUtils.readBytes(buffer, 4);
|
||||
tileFlags = BufferUtils.readBytes(buffer, NUM_SUBTILES);
|
||||
zeros2 = BufferUtils.readBytes(buffer, 7);
|
||||
blockHeadersPointer = buffer.getInt();
|
||||
blockDataLength = buffer.getInt();
|
||||
numBlocks = buffer.getInt();
|
||||
zeros3 = BufferUtils.readBytes(buffer, 12);
|
||||
id = Index.create(orientation, mainIndex, subIndex);
|
||||
assert !buffer.hasRemaining();
|
||||
assert allZeros(zeros1) : "Expected 4 zeros, got: " + Arrays.toString(zeros1);
|
||||
assert allZeros(zeros2) : "Expected 7 zeros, got: " + Arrays.toString(zeros2);
|
||||
//assert allZeros(zeros3) : "Expected 12 zeros, got: " + Arrays.toString(zeros3);
|
||||
}
|
||||
|
||||
public int getNumBlocks() {
|
||||
return numBlocks;
|
||||
}
|
||||
|
||||
public Block getBlock(int i) {
|
||||
return blocks[i];
|
||||
}
|
||||
|
||||
public boolean isSpecial() {
|
||||
return Orientation.isSpecial(orientation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this)
|
||||
.append("id", "0x" + Integer.toHexString(id))
|
||||
.append("direction", direction)
|
||||
.append("roofHeight", roofHeight)
|
||||
.append("soundIndex", soundIndex)
|
||||
.append("animated", animated)
|
||||
.append("height", height)
|
||||
.append("width", width)
|
||||
//.append("zeros1", Arrays.toString(zeros1))
|
||||
.append("orientation", orientation)
|
||||
.append("mainIndex", mainIndex)
|
||||
.append("subIndex", subIndex)
|
||||
.append("rarity", rarity)
|
||||
.append("unknown", Arrays.toString(unknown))
|
||||
.append("tileFlags", Arrays.toString(tileFlags))
|
||||
//.append("zeros2", Arrays.toString(zeros2))
|
||||
.append("blockHeadersPointer", "0x" + Integer.toHexString(blockHeadersPointer))
|
||||
.append("blockDataLength", blockDataLength)
|
||||
.append("numBlocks", numBlocks)
|
||||
//.append("zeros3", Arrays.toString(zeros3))
|
||||
.toString();
|
||||
}
|
||||
|
||||
public void createPixmap() {
|
||||
Preconditions.checkState(pixmap == null, "pixmap should be null");
|
||||
int absWidth = width;
|
||||
int absHeight = -height;
|
||||
|
||||
if (isSpecial()) {
|
||||
absWidth = WIDTH;
|
||||
}
|
||||
|
||||
int y_add = 96;
|
||||
if (orientation == Orientation.FLOOR || orientation == Orientation.ROOF) {
|
||||
if (height != 0) {
|
||||
height = -80;
|
||||
absHeight = 80;
|
||||
y_add = 0;
|
||||
}
|
||||
} else if (orientation < Orientation.ROOF) {
|
||||
if (height != 0) {
|
||||
height += 32;
|
||||
absHeight -= 32;
|
||||
y_add = absHeight;
|
||||
}
|
||||
}
|
||||
|
||||
int x0, y0, length, format;
|
||||
byte[] data;
|
||||
|
||||
pixmap = new PaletteIndexedPixmap(absWidth, absHeight);
|
||||
for (Block block : blocks) {
|
||||
x0 = block.x;
|
||||
y0 = y_add + block.y;
|
||||
data = block.colormap;
|
||||
length = block.length;
|
||||
format = block.format;
|
||||
if (format == 0x0001) {
|
||||
drawIsometricBlock(x0, y0, data, length);
|
||||
} else {
|
||||
drawRLEBlock(x0, y0, data, length);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void drawIsometricBlock(int x0, int y0, byte[] data, int length) {
|
||||
if (length != 256) {
|
||||
Gdx.app.error(TAG, "Blocks should be 256 bytes, was " + length);
|
||||
return;
|
||||
}
|
||||
|
||||
int x, y = 0, n, i = 0;
|
||||
while (length > 0) {
|
||||
x = X_JUMP[y];
|
||||
n = PIXEL_WIDTH[y];
|
||||
length -= n;
|
||||
while (n > 0) {
|
||||
pixmap.drawPixel(x0 + x, y0 + y, Palette.a8(data[i]));
|
||||
i++;
|
||||
x++;
|
||||
n--;
|
||||
}
|
||||
y++;
|
||||
}
|
||||
}
|
||||
|
||||
private void drawRLEBlock(int x0, int y0, byte[] data, int length) {
|
||||
int i = 0, b1, b2;
|
||||
int x = 0, y = 0;
|
||||
while (length > 0) {
|
||||
b1 = data[i] & 0xFF;
|
||||
b2 = data[i + 1] & 0xFF;
|
||||
i += 2;
|
||||
length -= 2;
|
||||
if (b1 > 0 || b2 > 0) {
|
||||
x += b1;
|
||||
length -= b2;
|
||||
while (b2 > 0) {
|
||||
pixmap.drawPixel(x0 + x, y0 + y, Palette.a8(data[i]));
|
||||
i++;
|
||||
x++;
|
||||
b2--;
|
||||
}
|
||||
} else {
|
||||
x = 0;
|
||||
y++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Index {
|
||||
private static final int MAIN_INDEX_OFFSET = 16;
|
||||
private static final int MAIN_INDEX_BITS = 0xFF;
|
||||
|
||||
private static final int SUB_INDEX_OFFSET = 8;
|
||||
private static final int SUB_INDEX_BITS = 0xFF;
|
||||
|
||||
private static final int ORIENTATION_OFFSET = 0;
|
||||
private static final int ORIENTATION_BITS = 0xFF;
|
||||
|
||||
public static int create(int orientation, int mainIndex, int subIndex) {
|
||||
return (mainIndex & MAIN_INDEX_BITS) << MAIN_INDEX_OFFSET
|
||||
| (subIndex & SUB_INDEX_BITS) << SUB_INDEX_OFFSET
|
||||
| (orientation & ORIENTATION_BITS) << ORIENTATION_OFFSET;
|
||||
}
|
||||
|
||||
public static int mainIndex(int index) {
|
||||
return (index >>> MAIN_INDEX_OFFSET) & MAIN_INDEX_BITS;
|
||||
}
|
||||
|
||||
public static int subIndex(int index) {
|
||||
return (index >>> SUB_INDEX_OFFSET) & SUB_INDEX_BITS;
|
||||
}
|
||||
|
||||
public static int orientation(int index) {
|
||||
return (index >>> ORIENTATION_OFFSET) & ORIENTATION_BITS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Block {
|
||||
static final int SIZE = 20;
|
||||
|
||||
public short x;
|
||||
public short y;
|
||||
public byte zeros1[];
|
||||
public byte gridX;
|
||||
public byte gridY;
|
||||
public short format;
|
||||
public int length;
|
||||
public byte zeros2[];
|
||||
public int fileOffset;
|
||||
|
||||
public byte colormap[];
|
||||
|
||||
Block(InputStream in) throws IOException {
|
||||
ByteBuffer buffer = ByteBuffer.wrap(IOUtils.readFully(in, SIZE)).order(ByteOrder.LITTLE_ENDIAN);
|
||||
x = buffer.getShort();
|
||||
y = buffer.getShort();
|
||||
zeros1 = BufferUtils.readBytes(buffer, 2);
|
||||
gridX = buffer.get();
|
||||
gridY = buffer.get();
|
||||
format = buffer.getShort();
|
||||
length = buffer.getInt();
|
||||
zeros2 = BufferUtils.readBytes(buffer, 2);
|
||||
fileOffset = buffer.getInt();
|
||||
assert !buffer.hasRemaining();
|
||||
assert allZeros(zeros1) : "Expected 2 zeros, got: " + Arrays.toString(zeros1);
|
||||
assert allZeros(zeros2) : "Expected 2 zeros, got: " + Arrays.toString(zeros2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this)
|
||||
.append("x", x)
|
||||
.append("y", y)
|
||||
//.append("zeros1", Arrays.toString(zeros1))
|
||||
.append("gridX", gridX)
|
||||
.append("gridY", gridY)
|
||||
.append("format", format)
|
||||
.append("length", length)
|
||||
//.append("zeros2", Arrays.toString(zeros2))
|
||||
.append("fileOffset", "0x" + Integer.toHexString(fileOffset))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
package gdx.diablo.map2;
|
||||
|
||||
import com.badlogic.gdx.assets.AssetDescriptor;
|
||||
import com.badlogic.gdx.assets.AssetLoaderParameters;
|
||||
import com.badlogic.gdx.assets.AssetManager;
|
||||
import com.badlogic.gdx.assets.loaders.AsynchronousAssetLoader;
|
||||
import com.badlogic.gdx.assets.loaders.FileHandleResolver;
|
||||
import com.badlogic.gdx.files.FileHandle;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
|
||||
public class DT1Loader extends AsynchronousAssetLoader<DT1, DT1Loader.DT1LoaderParameters> {
|
||||
|
||||
DT1 dt1;
|
||||
|
||||
public DT1Loader(FileHandleResolver resolver) {
|
||||
super(resolver);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadAsync(AssetManager assets, String fileName, FileHandle file, DT1LoaderParameters params) {
|
||||
dt1 = DT1.loadFromStream(fileName, file.read());
|
||||
}
|
||||
|
||||
@Override
|
||||
public DT1 loadSync(AssetManager assets, String fileName, FileHandle file, DT1LoaderParameters params) {
|
||||
DT1 dt1 = this.dt1;
|
||||
if (dt1 == null) {
|
||||
dt1 = DT1.loadFromStream(fileName, file.read());
|
||||
} else {
|
||||
this.dt1 = null;
|
||||
}
|
||||
|
||||
dt1.prepareTextures();
|
||||
return dt1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Array<AssetDescriptor> getDependencies(String fileName, FileHandle file, DT1LoaderParameters params) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static class DT1LoaderParameters extends AssetLoaderParameters<DT1> {}
|
||||
|
||||
}
|
@ -1,72 +0,0 @@
|
||||
package gdx.diablo.map2;
|
||||
|
||||
import com.badlogic.gdx.math.MathUtils;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.IntIntMap;
|
||||
import com.badlogic.gdx.utils.IntMap;
|
||||
import com.badlogic.gdx.utils.ObjectSet;
|
||||
|
||||
public class DT1s {
|
||||
// TODO: tiles and prob are both keyed with tile ID, can speed up if using one map to Pair<prob, tiles>
|
||||
ObjectSet<DT1> dt1s = new ObjectSet<>();
|
||||
IntMap<Array<DT1.Tile>> tiles = new IntMap<>();
|
||||
IntIntMap prob = new IntIntMap();
|
||||
|
||||
void add(DT1.Tile tile) {
|
||||
//if (tile.rarity == 0) return;
|
||||
Array<DT1.Tile> tiles = this.tiles.get(tile.id);
|
||||
if (tiles == null) this.tiles.put(tile.id, tiles = new Array<>());
|
||||
tiles.add(tile);
|
||||
prob.getAndIncrement(tile.id, 0, tile.rarity);
|
||||
}
|
||||
|
||||
void remove(DT1.Tile tile) {
|
||||
//if (tile.rarity == 0) return;
|
||||
Array<DT1.Tile> tiles = this.tiles.get(tile.id);
|
||||
if (tiles == null) return;
|
||||
tiles.removeValue(tile, true);
|
||||
prob.getAndIncrement(tile.id, 0, -tile.rarity);
|
||||
}
|
||||
|
||||
public boolean add(DT1 dt1) {
|
||||
if (!dt1s.add(dt1)) return false;
|
||||
for (DT1.Tile tile : dt1.tiles) add(tile);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean remove(DT1 dt1) {
|
||||
if (!dt1s.remove(dt1)) return false;
|
||||
for (DT1.Tile tile : dt1.tiles) remove(tile);
|
||||
return true;
|
||||
}
|
||||
|
||||
public DT1.Tile get(int orientation, int mainIndex, int subIndex) {
|
||||
int id = DT1.Tile.Index.create(orientation, mainIndex, subIndex);
|
||||
Array<DT1.Tile> tiles = this.tiles.get(id);
|
||||
return next(id, tiles);
|
||||
}
|
||||
|
||||
public DT1.Tile get(DS1.Cell cell) {
|
||||
Array<DT1.Tile> tiles = this.tiles.get(cell.id);
|
||||
return next(cell.id, tiles);
|
||||
}
|
||||
|
||||
public DT1.Tile get(int id) {
|
||||
Array<DT1.Tile> tiles = this.tiles.get(id);
|
||||
return next(id, tiles);
|
||||
}
|
||||
|
||||
private DT1.Tile next(int id, Array<DT1.Tile> tiles) {
|
||||
if (tiles == null) return null;
|
||||
int sum = prob.get(id, 0);
|
||||
int random = sum == 0 ? 0 : MathUtils.random(sum - 1);
|
||||
for (DT1.Tile tile : tiles) {
|
||||
random -= tile.rarity;
|
||||
if (random <= 0) {
|
||||
return tile;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,461 +0,0 @@
|
||||
package gdx.diablo.map2;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.math.GridPoint2;
|
||||
import com.badlogic.gdx.math.MathUtils;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.IntMap;
|
||||
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import gdx.diablo.Diablo;
|
||||
import gdx.diablo.codec.excel.Levels;
|
||||
import gdx.diablo.codec.excel.LvlPrest;
|
||||
import gdx.diablo.codec.excel.LvlTypes;
|
||||
|
||||
public class Map {
|
||||
private static final String TAG = "Map";
|
||||
private static final boolean DEBUG = true;
|
||||
private static final boolean DEBUG_BUILD = DEBUG && true;
|
||||
|
||||
public static final String TILES_PATH = "data/global/tiles/";
|
||||
|
||||
public static final int OUTDOOR_GRID_X = 8;
|
||||
public static final int OUTDOOR_GRID_Y = 8;
|
||||
|
||||
private static final int DIRECTION_NORTH = 0;
|
||||
private static final int DIRECTION_EAST = 1;
|
||||
private static final int DIRECTION_SOUTH = 2;
|
||||
private static final int DIRECTION_WEST = 3;
|
||||
|
||||
private static final int[] ACT_DEF = new int[]{1, 301, 529, 797, 863};
|
||||
|
||||
public static final int ID_MAP_ENTRY = DT1.Tile.Index.create(Orientation.SPECIAL_TILE_11, 30, 0);
|
||||
public static final int ID_TOWN_ENTRY_1 = DT1.Tile.Index.create(Orientation.SPECIAL_TILE_10, 30, 0);
|
||||
public static final int ID_TOWN_ENTRY_2 = DT1.Tile.Index.create(Orientation.SPECIAL_TILE_10, 31, 0);
|
||||
public static final int ID_CORPSE_LOCATION = DT1.Tile.Index.create(Orientation.SPECIAL_TILE_10, 32, 0);
|
||||
public static final int ID_TP_LOCATION = DT1.Tile.Index.create(Orientation.SPECIAL_TILE_10, 33, 0);
|
||||
static IntMap<String> ID_TO_NAME;
|
||||
static {
|
||||
ID_TO_NAME = new IntMap<>();
|
||||
ID_TO_NAME.put(ID_MAP_ENTRY, "ID_MAP_ENTRY");
|
||||
ID_TO_NAME.put(ID_TOWN_ENTRY_1, "ID_TOWN_ENTRY_1");
|
||||
ID_TO_NAME.put(ID_TOWN_ENTRY_2, "ID_TOWN_ENTRY_2");
|
||||
ID_TO_NAME.put(ID_CORPSE_LOCATION, "ID_CORPSE_LOCATION");
|
||||
ID_TO_NAME.put(ID_TP_LOCATION, "ID_TP_LOCATION");
|
||||
}
|
||||
|
||||
public int width;
|
||||
public int height;
|
||||
|
||||
public static Map build(int seed, int act, int diff) {
|
||||
MathUtils.random.setSeed(seed);
|
||||
|
||||
Map map = new Map();
|
||||
|
||||
int def = ACT_DEF[act];
|
||||
LvlPrest.Entry preset = Diablo.files.LvlPrest.get(def);
|
||||
Levels.Entry level = Diablo.files.Levels.get(preset.LevelId);
|
||||
if (DEBUG_BUILD) Gdx.app.debug(TAG, level.LevelName);
|
||||
|
||||
int fileId[] = new int[6];
|
||||
int numFiles = getPresets(preset, fileId);
|
||||
int select = MathUtils.random(numFiles - 1);
|
||||
String fileName = preset.File[select];
|
||||
if (DEBUG_BUILD) Gdx.app.debug(TAG, "Select " + fileName);
|
||||
|
||||
Zone zone = map.addZone(level, diff, preset, select);
|
||||
map.width = zone.width;
|
||||
map.height = zone.height;
|
||||
Zone prev = zone;
|
||||
|
||||
level = Diablo.files.Levels.get(2);
|
||||
zone = map.addZone(level, diff, 8, 8);
|
||||
zone.x = prev.width - zone.width;
|
||||
zone.y = -zone.height;
|
||||
|
||||
Preset SB = Preset.of(Diablo.files.LvlPrest.get(4), 0);
|
||||
Preset EB = Preset.of(Diablo.files.LvlPrest.get(5), 0);
|
||||
Preset NB = Preset.of(Diablo.files.LvlPrest.get(6), 0);
|
||||
Preset WB = Preset.of(Diablo.files.LvlPrest.get(7), 0);
|
||||
Preset NWB = Preset.of(Diablo.files.LvlPrest.get(9), 0);
|
||||
Preset LRC = Preset.of(Diablo.files.LvlPrest.get(27), 0);
|
||||
Preset UR = Preset.of(Diablo.files.LvlPrest.get(26), 3);
|
||||
Preset URNB = Preset.of(Diablo.files.LvlPrest.get(26), 1);
|
||||
Preset SWB = Preset.of(Diablo.files.LvlPrest.get(8), 0);
|
||||
Preset LB = Preset.of(Diablo.files.LvlPrest.get(12), 0);
|
||||
Preset FILL[] = Preset.of(Diablo.files.LvlPrest.get(29));
|
||||
|
||||
for (int x = 0; x < zone.gridsX; x++) {
|
||||
for (int y = 0; y < zone.gridsY; y++) {
|
||||
zone.presets[x][y] = FILL[MathUtils.random(FILL.length - 1)];
|
||||
}
|
||||
}
|
||||
for (int y = 0; y < zone.gridsY; y++) {
|
||||
zone.presets[0][y] = EB;
|
||||
zone.presets[zone.gridsX - 2][y] = UR;
|
||||
zone.presets[zone.gridsX - 1][y] = LRC;
|
||||
}
|
||||
for (int x = 1; x < zone.gridsX - 1; x++) {
|
||||
zone.presets[x][0] = NB;
|
||||
}
|
||||
zone.presets[0][0] = NWB;
|
||||
zone.presets[zone.gridsX - 2][0] = URNB;
|
||||
zone.presets[zone.gridsX - 1][0] = LRC;
|
||||
zone.presets[0][zone.gridsY - 1] = SWB;
|
||||
zone.presets[1][zone.gridsY - 1] = SB;
|
||||
zone.presets[2][zone.gridsY - 1] = SB;
|
||||
zone.presets[3][zone.gridsY - 1] = LB;
|
||||
|
||||
zone.presets[6][zone.gridsY - 2] = Preset.of(Diablo.files.LvlPrest.get(47), 1);
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
public GridPoint2 find(int id) {
|
||||
return zones.first().presets[0][0].ds1.find(id);
|
||||
}
|
||||
|
||||
public GridPoint2 find(int orientation, int mainIndex, int subIndex) {
|
||||
int id = DT1.Tile.Index.create(orientation, mainIndex, subIndex);
|
||||
return find(id);
|
||||
}
|
||||
|
||||
public String getSpecialName(int id) {
|
||||
return ID_TO_NAME.get(id, "null");
|
||||
}
|
||||
|
||||
private static int getPresets(LvlPrest.Entry preset, int[] fileIds) {
|
||||
int numFiles = 0;
|
||||
Arrays.fill(fileIds, -1);
|
||||
for (int i = 0; i < preset.File.length; i++) {
|
||||
if (preset.File[i].charAt(0) != '0') {
|
||||
fileIds[numFiles++] = i;
|
||||
}
|
||||
}
|
||||
|
||||
return numFiles;
|
||||
}
|
||||
|
||||
Array<Zone> zones = new Array<>();
|
||||
|
||||
public void load() {
|
||||
for (Zone zone : zones) {
|
||||
for (int x = 0; x < zone.gridsX; x++) {
|
||||
for (int y = 0; y < zone.gridsY; y++) {
|
||||
Map.Preset preset = zone.presets[x][y];
|
||||
if (preset == null) continue;
|
||||
|
||||
Diablo.assets.load(TILES_PATH + preset.ds1Name, DS1.class);
|
||||
|
||||
int DT1Mask = preset.preset.Dt1Mask;
|
||||
for (int i = 0; i < Integer.SIZE; i++) {
|
||||
if ((DT1Mask & (1 << i)) != 0) {
|
||||
String dt1 = TILES_PATH + zone.type.File[i];
|
||||
Diablo.assets.load(dt1, DT1.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Diablo.assets.finishLoading();
|
||||
for (Zone zone : zones) {
|
||||
zone.load();
|
||||
}
|
||||
}
|
||||
|
||||
Zone addZone(Levels.Entry level, int diff, LvlPrest.Entry preset, int ds1) {
|
||||
assert preset.LevelId != 0 : "presets should have an assigned level id";
|
||||
Zone zone = addZone(level, diff, level.SizeX[diff], level.SizeY[diff]);
|
||||
zone.presets[0][0] = Preset.of(preset, ds1);
|
||||
return zone;
|
||||
}
|
||||
|
||||
Zone addZone(Levels.Entry level, int diff, int gridSizeX, int gridSizeY) {
|
||||
Zone zone = new Zone(gridSizeX, gridSizeY);
|
||||
zone.level = level;
|
||||
zone.type = Diablo.files.LvlTypes.get(level.LevelType);
|
||||
zone.width = level.SizeX[diff];
|
||||
zone.height = level.SizeY[diff];
|
||||
zone.gridsX = zone.width / zone.gridSizeX;
|
||||
zone.gridsY = zone.height / zone.gridSizeY;
|
||||
zone.presets = new Preset[zone.gridsX][zone.gridsY];
|
||||
zone.flags = new byte[zone.width * DT1.Tile.SUBTILE_SIZE][zone.height * DT1.Tile.SUBTILE_SIZE];
|
||||
zones.add(zone);
|
||||
return zone;
|
||||
}
|
||||
|
||||
Zone getZone(int x, int y) {
|
||||
for (Zone zone : zones) {
|
||||
if (zone.contains(x, y)) {
|
||||
return zone;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
static class Zone {
|
||||
int x, y;
|
||||
int width, height;
|
||||
int gridSizeX, gridSizeY;
|
||||
int gridsX, gridsY;
|
||||
Levels.Entry level;
|
||||
LvlTypes.Entry type;
|
||||
Preset presets[][];
|
||||
Tile tiles[][][];
|
||||
byte flags[][];
|
||||
|
||||
public Zone(int gridSizeX, int gridSizeY) {
|
||||
this.gridSizeX = gridSizeX;
|
||||
this.gridSizeY = gridSizeY;
|
||||
}
|
||||
|
||||
public boolean contains(int x, int y) {
|
||||
x -= this.x;
|
||||
y -= this.y;
|
||||
return 0 <= x && x < width
|
||||
&& 0 <= y && y < height;
|
||||
}
|
||||
|
||||
public Tile get(int layer, int x, int y) {
|
||||
return tiles[layer] == null ? null : tiles[layer][x - this.x][y - this.y];
|
||||
}
|
||||
|
||||
public int getLocalX(int x) {
|
||||
return x - this.x;
|
||||
}
|
||||
|
||||
public int getLocalY(int y) {
|
||||
return y - this.y;
|
||||
}
|
||||
|
||||
void load() {
|
||||
Preconditions.checkState(tiles == null, "tiles have already been loaded");
|
||||
tiles = new Tile[DS1.MAX_LAYERS][][];
|
||||
for (int x = 0, gridX = 0, gridY = 0; x < gridsX; x++, gridX += gridSizeX, gridY = 0) {
|
||||
for (int y = 0; y < gridsY; y++, gridY += gridSizeY) {
|
||||
Preset preset = presets[x][y];
|
||||
DS1 ds1 = Diablo.assets.get(TILES_PATH + preset.ds1Name);
|
||||
preset.load(this, ds1, gridX, gridY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
ToStringBuilder builder = new ToStringBuilder(this);
|
||||
if (level != null) {
|
||||
builder
|
||||
.append("name", level.LevelName)
|
||||
.append("id", level.Id);
|
||||
}
|
||||
|
||||
return builder
|
||||
.append("x", x)
|
||||
.append("y", y)
|
||||
.append("width", width)
|
||||
.append("height", height)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
static class Tile {
|
||||
DT1.Tile tile;
|
||||
DS1.Cell cell;
|
||||
//byte[] flags;
|
||||
|
||||
public static Tile of(DS1.Cell cell) {
|
||||
return of(Diablo.dt1s.get(cell), cell);
|
||||
}
|
||||
|
||||
public static Tile of(DT1.Tile tile, DS1.Cell cell) {
|
||||
Tile t = new Tile();
|
||||
t.tile = tile;
|
||||
t.cell = cell;
|
||||
//t.flags = new byte[DT1.Tile.NUM_SUBTILES];
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
static class Preset {
|
||||
LvlPrest.Entry preset;
|
||||
String ds1Name;
|
||||
DS1 ds1;
|
||||
|
||||
public static Preset of(LvlPrest.Entry preset, int ds1) {
|
||||
Preset p = new Preset();
|
||||
p.preset = preset;
|
||||
p.ds1Name = preset.File[ds1];
|
||||
return p;
|
||||
}
|
||||
|
||||
public static Preset of(LvlPrest.Entry preset, String ds1) {
|
||||
Preset p = new Preset();
|
||||
p.preset = preset;
|
||||
p.ds1Name = ds1;
|
||||
return p;
|
||||
}
|
||||
|
||||
public static Preset[] of(LvlPrest.Entry preset) {
|
||||
Preset[] presets = new Preset[preset.Files];
|
||||
for (int i = 0; i < preset.Files; i++) {
|
||||
presets[i] = Preset.of(preset, i);
|
||||
}
|
||||
|
||||
return presets;
|
||||
}
|
||||
|
||||
public void load(Zone zone, DS1 ds1, int x, int y) {
|
||||
assert x + ds1.width <= zone.width : "x=" + x + "; ds1.width=" + ds1.width + "; zone.width=" + zone.width;
|
||||
assert y + ds1.height <= zone.width : "y=" + y + "; ds1.height=" + ds1.height + "; zone.height=" + zone.height;
|
||||
|
||||
this.ds1 = ds1;
|
||||
loadFloors(zone, DS1.FLOOR_OFFSET, x, y, ds1);
|
||||
loadWalls(zone, DS1.WALL_OFFSET, x, y, ds1);
|
||||
//loadLayer(zone, FLOOR_OFFSET, x, y, ds1.floors, ds1.numFloors, ds1.floorLine);
|
||||
//loadLayer(zone, SHADOW_OFFSET, x, y, ds1.shadows, ds1.numShadows, ds1.shadowLine);
|
||||
//loadLayer(zone, WALL_OFFSET, x, y, ds1.walls, ds1.numWalls, ds1.wallLine);
|
||||
}
|
||||
|
||||
void loadLayer(Zone zone, int layer, int x, int y, DS1.Cell[] cells, int numLayers, int cellsLine) {
|
||||
final int X_OFFS = x, Y_OFFS = y;
|
||||
for (int i = 0, offsetX, offsetY; i < numLayers; i++, layer++) {
|
||||
offsetX = X_OFFS;
|
||||
offsetY = Y_OFFS;
|
||||
if (zone.tiles[layer] == null) zone.tiles[layer] = new Tile[zone.width][zone.height];
|
||||
for (y = 0; y < zone.height; y++, offsetY++, offsetX = X_OFFS) {
|
||||
//int ptr = i + (y * cellsLine);
|
||||
for (x = 0; x < zone.width; x++, offsetX++/*, ptr += numLayers*/) {
|
||||
int ptr = (y * cellsLine) + (x * numLayers);
|
||||
DS1.Cell cell = cells[ptr];
|
||||
zone.tiles[layer][offsetX][offsetY] = Tile.of(cell);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void loadFloors(Zone zone, int layer, int x, int y, DS1 ds1) {
|
||||
final int X_OFFS = x, Y_OFFS = y;
|
||||
for (int i = 0, offsetX, offsetY; i < ds1.numFloors; i++, layer++) {
|
||||
offsetX = X_OFFS;
|
||||
offsetY = Y_OFFS;
|
||||
if (zone.tiles[layer] == null) zone.tiles[layer] = new Tile[zone.width][zone.height];
|
||||
for (y = 0; y < ds1.height; y++, offsetY++, offsetX = X_OFFS) {
|
||||
for (x = 0; x < ds1.width; x++, offsetX++) {
|
||||
int ptr = i + (y * ds1.floorLine) + (x * ds1.numFloors);
|
||||
DS1.Cell cell = ds1.floors[ptr];
|
||||
|
||||
if ((cell.value & 0x00020000) != 0) {
|
||||
int offsetX2 = offsetX * DT1.Tile.SUBTILE_SIZE;
|
||||
int offsetY2 = offsetY * DT1.Tile.SUBTILE_SIZE;
|
||||
for (int y2 = 0; y2 < DT1.Tile.SUBTILE_SIZE; y2++) {
|
||||
for (int x2 = 0; x2 < DT1.Tile.SUBTILE_SIZE; x2++) {
|
||||
zone.flags[offsetX2 + x2][offsetY2 + y2] |= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ds1.numFloors == 1) {
|
||||
if ((ds1.floors[0].value & 0xFF) == 0) {
|
||||
int offsetX2 = offsetX * DT1.Tile.SUBTILE_SIZE;
|
||||
int offsetY2 = offsetY * DT1.Tile.SUBTILE_SIZE;
|
||||
for (int y2 = 0; y2 < DT1.Tile.SUBTILE_SIZE; y2++) {
|
||||
for (int x2 = 0; x2 < DT1.Tile.SUBTILE_SIZE; x2++) {
|
||||
zone.flags[offsetX2 + x2][offsetY2 + y2] |= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (ds1.numFloors == 2) {
|
||||
if ((ds1.floors[0].value & 0xFF) == 0 && (ds1.floors[1].value & 0xFF) == 0) {
|
||||
int offsetX2 = offsetX * DT1.Tile.SUBTILE_SIZE;
|
||||
int offsetY2 = offsetY * DT1.Tile.SUBTILE_SIZE;
|
||||
for (int y2 = 0; y2 < DT1.Tile.SUBTILE_SIZE; y2++) {
|
||||
for (int x2 = 0; x2 < DT1.Tile.SUBTILE_SIZE; x2++) {
|
||||
zone.flags[offsetX2 + x2][offsetY2 + y2] |= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((cell.value & 0x80000000) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Tile tile = zone.tiles[layer][offsetX][offsetY] = Tile.of(cell);
|
||||
copyFlags(zone.flags, offsetX, offsetY, tile.tile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void loadWalls(Zone zone, int layer, int x, int y, DS1 ds1) {
|
||||
final int X_OFFS = x, Y_OFFS = y;
|
||||
for (int i = 0, offsetX, offsetY; i < ds1.numWalls; i++, layer++) {
|
||||
offsetX = X_OFFS;
|
||||
offsetY = Y_OFFS;
|
||||
if (zone.tiles[layer] == null) zone.tiles[layer] = new Tile[zone.width][zone.height];
|
||||
for (y = 0; y < ds1.height; y++, offsetY++, offsetX = X_OFFS) {
|
||||
for (x = 0; x < ds1.width; x++, offsetX++) {
|
||||
int ptr = i + (y * ds1.wallLine) + (x * ds1.numWalls);
|
||||
DS1.Cell cell = ds1.walls[ptr];
|
||||
|
||||
if ((cell.value & DS1.Cell.MASK_UNWALKABLE) != 0) {
|
||||
int offsetX2 = offsetX * DT1.Tile.SUBTILE_SIZE;
|
||||
int offsetY2 = offsetY * DT1.Tile.SUBTILE_SIZE;
|
||||
for (int y2 = 0; y2 < DT1.Tile.SUBTILE_SIZE; y2++) {
|
||||
for (int x2 = 0; x2 < DT1.Tile.SUBTILE_SIZE; x2++) {
|
||||
zone.flags[offsetX2 + x2][offsetY2 + y2] |= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((cell.value & 0x80000000) != 0) {
|
||||
// This seems like all the special tiles, null usually means marker tile (start pos),
|
||||
// non null usually means stuff like side of river, used for ?weather? ?rain drops?
|
||||
if (!Orientation.isSpecial(cell.orientation)) {
|
||||
//DT1.Tile tile = Diablo.dt1s.get(cell);
|
||||
//System.out.println(x + ", " + y + " " + tile);
|
||||
continue;
|
||||
}
|
||||
|
||||
zone.tiles[layer][offsetX][offsetY] = Tile.of(cell);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (cell.orientation == Orientation.FLOOR) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Tile tile = zone.tiles[layer][offsetX][offsetY] = Tile.of(cell);
|
||||
copyFlags(zone.flags, offsetX, offsetY, tile.tile);
|
||||
|
||||
// Special case, because LEFT_NORTH_CORNER_WALL don't seem to exist, but they contain
|
||||
// collision data for RIGHT_NORTH_CORNER_WALL, ORing the data just in case some
|
||||
// RIGHT_NORTH_CORNER_WALL actually does anything
|
||||
if (cell.orientation == Orientation.RIGHT_NORTH_CORNER_WALL) {
|
||||
DT1.Tile leftSide = Diablo.dt1s.get(Orientation.LEFT_NORTH_CORNER_WALL, cell.mainIndex, cell.subIndex);
|
||||
copyFlags(zone.flags, offsetX, offsetY, leftSide);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void copyFlags(byte[][] flags, int tx, int ty, DT1.Tile tile) {
|
||||
int offsetX = tx * DT1.Tile.SUBTILE_SIZE;
|
||||
int offsetY = ty * DT1.Tile.SUBTILE_SIZE;
|
||||
// Note: walkable flags are stored inverted y-axis, this corrects it
|
||||
for (int y = DT1.Tile.SUBTILE_SIZE - 1, t = 0; y >= 0; y--) {
|
||||
for (int x = 0; x < DT1.Tile.SUBTILE_SIZE; x++, t++) {
|
||||
flags[offsetX + x][offsetY + y] |= tile.tileFlags[t];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,588 +0,0 @@
|
||||
package gdx.diablo.map2;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.graphics.Color;
|
||||
import com.badlogic.gdx.graphics.OrthographicCamera;
|
||||
import com.badlogic.gdx.graphics.g2d.GlyphLayout;
|
||||
import com.badlogic.gdx.graphics.glutils.ShapeRenderer;
|
||||
import com.badlogic.gdx.math.Rectangle;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import gdx.diablo.Diablo;
|
||||
import gdx.diablo.codec.FontTBL;
|
||||
import gdx.diablo.graphics.PaletteIndexedBatch;
|
||||
|
||||
public class MapRenderer {
|
||||
private static final String TAG = "MapRenderer";
|
||||
private static final boolean DEBUG = true;
|
||||
private static final boolean DEBUG_MATH = DEBUG && !true;
|
||||
private static final boolean DEBUG_BUFFER = DEBUG && true;
|
||||
private static final boolean DEBUG_SUBTILE = DEBUG && true;
|
||||
private static final boolean DEBUG_TILE = DEBUG && true;
|
||||
private static final boolean DEBUG_CAMERA = DEBUG && true;
|
||||
private static final boolean DEBUG_OVERSCAN = DEBUG && true;
|
||||
private static final boolean DEBUG_GRID = DEBUG && true;
|
||||
private static final boolean DEBUG_WALKABLE = DEBUG && !true;
|
||||
private static final boolean DEBUG_SPECIAL = DEBUG && true;
|
||||
|
||||
public static boolean RENDER_DEBUG_SUBTILE = DEBUG_SUBTILE;
|
||||
public static boolean RENDER_DEBUG_TILE = DEBUG_TILE;
|
||||
public static boolean RENDER_DEBUG_CAMERA = DEBUG_CAMERA;
|
||||
public static boolean RENDER_DEBUG_OVERSCAN = DEBUG_OVERSCAN;
|
||||
public static int RENDER_DEBUG_GRID = DEBUG_GRID ? 3 : 0;
|
||||
public static int RENDER_DEBUG_WALKABLE = DEBUG_WALKABLE ? DS1.MAX_LAYERS + 1 : 0;
|
||||
public static boolean RENDER_DEBUG_SPECIAL = DEBUG_SPECIAL;
|
||||
|
||||
private static final Color RENDER_DEBUG_GRID_COLOR_1 = new Color(0x3f3f3f3f);
|
||||
private static final Color RENDER_DEBUG_GRID_COLOR_2 = new Color(0x7f7f7f3f);
|
||||
private static final Color RENDER_DEBUG_GRID_COLOR_3 = new Color(0x0000ff3f);
|
||||
public static int DEBUG_GRID_MODES = 3;
|
||||
|
||||
PaletteIndexedBatch batch;
|
||||
OrthographicCamera camera;
|
||||
Map map;
|
||||
Rectangle viewBounds;
|
||||
int[] viewBuffer;
|
||||
float factor = -1.0f;
|
||||
|
||||
final int tileWidth = DT1.Tile.WIDTH;
|
||||
final int tileHeight = DT1.Tile.HEIGHT;
|
||||
final int halfTileWidth = tileWidth >>> 1;
|
||||
final int halfTileHeight = tileHeight >>> 1;
|
||||
|
||||
final int subTileWidth = DT1.Tile.SUBTILE_WIDTH;
|
||||
final int subTileHeight = DT1.Tile.SUBTILE_HEIGHT;
|
||||
final int halfSubTileWidth = subTileWidth >>> 1;
|
||||
final int halfSubTileHeight = subTileHeight >>> 1;
|
||||
|
||||
// subtile index in world-space
|
||||
int x, y;
|
||||
|
||||
// subtile index in tile-space
|
||||
int stx, sty;
|
||||
|
||||
// subtile index in tile-space 1D
|
||||
int t;
|
||||
|
||||
// pixel offset of subtile in world-space
|
||||
int spx, spy;
|
||||
|
||||
// tile index in world-space
|
||||
int tx, ty;
|
||||
|
||||
// pixel offset of tile in world-space
|
||||
int tpx, tpy;
|
||||
|
||||
int width, height;
|
||||
int tilesX, tilesY;
|
||||
int renderWidth, renderHeight;
|
||||
|
||||
// tile index of top right tile in render area
|
||||
int startX, startY;
|
||||
|
||||
// tpx and tpy of startX, startY tile in world-space
|
||||
int startPx, startPy;
|
||||
|
||||
private static final Color SHADOW_TINT = new Color(0, 0, 0, 0.5f);
|
||||
|
||||
public MapRenderer(PaletteIndexedBatch batch, OrthographicCamera camera) {
|
||||
this.batch = batch;
|
||||
this.camera = camera;
|
||||
viewBounds = new Rectangle();
|
||||
}
|
||||
|
||||
public void setMap(Map map) {
|
||||
if (this.map != map) {
|
||||
this.map = map;
|
||||
}
|
||||
}
|
||||
|
||||
public void update() {
|
||||
float width = camera.viewportWidth * camera.zoom;
|
||||
float height = camera.viewportHeight * camera.zoom;
|
||||
float w = width * Math.abs(camera.up.y) + height * Math.abs(camera.up.x);
|
||||
float h = height * Math.abs(camera.up.y) + width * Math.abs(camera.up.x);
|
||||
float x = camera.position.x - w / 2;
|
||||
float y = camera.position.y - h / 2;
|
||||
viewBounds.set(x, y, width, height);
|
||||
}
|
||||
|
||||
public void setFactor(float factor) {
|
||||
if (this.factor != factor) {
|
||||
this.factor = factor;
|
||||
updateViewBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateViewBuffer() {
|
||||
/*
|
||||
int width = (int) viewBounds.width;
|
||||
int height = (int) viewBounds.height;
|
||||
if (factor == 0) {
|
||||
// FIXME: This isn't correct, but should be sufficiently large enough
|
||||
width = 8 * width;
|
||||
height = 8 * height;
|
||||
} else {
|
||||
width *= factor;
|
||||
height *= factor;
|
||||
}
|
||||
*/
|
||||
|
||||
updateBounds();
|
||||
// This will generate an array s.t. each cell is the length of tiles to render
|
||||
final int viewBufferLen = tilesX + tilesY - 1;
|
||||
final int viewBufferMax = tilesX * 2 - 1;
|
||||
viewBuffer = new int[viewBufferLen];
|
||||
int x, y;
|
||||
for (x = 0, y = 1; y < viewBufferMax; x++, y += 2)
|
||||
viewBuffer[x] = viewBuffer[viewBufferLen - 1 - x] = y;
|
||||
while (viewBuffer[x] == 0)
|
||||
viewBuffer[x++] = viewBufferMax;
|
||||
if (DEBUG_BUFFER) Gdx.app.debug(TAG, "viewBuffer=" + Arrays.toString(viewBuffer));
|
||||
}
|
||||
|
||||
public void setPosition(int x, int y) {
|
||||
if (this.x != x || this.y != y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
final int halfSubTileWidth = DT1.Tile.SUBTILE_WIDTH >>> 1;
|
||||
final int halfSubTileHeight = DT1.Tile.SUBTILE_HEIGHT >>> 1;
|
||||
int spx = (x * halfSubTileWidth) - (y * halfSubTileWidth);
|
||||
int spy = -(x * halfSubTileHeight) - (y * halfSubTileHeight);
|
||||
camera.position.set(spx, spy, 0);
|
||||
runMath(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
public void runMath(int x, int y) {
|
||||
camera.update();
|
||||
// subtile index in tile-space
|
||||
stx = x < 0
|
||||
? (x + 1) % DT1.Tile.SUBTILE_SIZE + (DT1.Tile.SUBTILE_SIZE - 1)
|
||||
: x % DT1.Tile.SUBTILE_SIZE;
|
||||
sty = y < 0
|
||||
? (y + 1) % DT1.Tile.SUBTILE_SIZE + (DT1.Tile.SUBTILE_SIZE - 1)
|
||||
: y % DT1.Tile.SUBTILE_SIZE;
|
||||
t = DT1.Tile.SUBTILE_INDEX[stx][sty];
|
||||
|
||||
// pixel offset of subtile in world-space
|
||||
spx = -halfSubTileWidth + (x * halfSubTileWidth) - (y * halfSubTileWidth);
|
||||
spy = -halfSubTileHeight - (x * halfSubTileHeight) - (y * halfSubTileHeight);
|
||||
|
||||
// tile index in world-space
|
||||
tx = x < 0
|
||||
? ((x + 1) / DT1.Tile.SUBTILE_SIZE) - 1
|
||||
: (x / DT1.Tile.SUBTILE_SIZE);
|
||||
ty = y < 0
|
||||
? ((y + 1) / DT1.Tile.SUBTILE_SIZE) - 1
|
||||
: (y / DT1.Tile.SUBTILE_SIZE);
|
||||
|
||||
tpx = spx - DT1.Tile.SUBTILE_OFFSET[t][0];
|
||||
tpy = spy - DT1.Tile.SUBTILE_OFFSET[t][1];
|
||||
|
||||
updateBounds();
|
||||
|
||||
final int offX = tilesX >>> 1;
|
||||
final int offY = tilesY >>> 1;
|
||||
startX = tx + offX - offY;
|
||||
startY = ty - offX - offY;
|
||||
startPx = tpx + renderWidth / 2 - halfTileWidth;
|
||||
startPy = tpy + renderHeight / 2 - halfTileHeight;
|
||||
|
||||
if (DEBUG_MATH) {
|
||||
Gdx.app.debug(TAG, String.format("(%2d,%2d){%d,%d}[%2d,%2d](%dx%d)[%dx%d] %d,%d%n",
|
||||
x, y, stx, sty, tx, ty, width, height, tilesX, tilesY, spx, spy));
|
||||
}
|
||||
}
|
||||
|
||||
private void updateBounds() {
|
||||
width = (int) camera.viewportWidth;
|
||||
height = (int) camera.viewportHeight;
|
||||
|
||||
int minTilesX = ((width + tileWidth - 1) / tileWidth);
|
||||
int minTilesY = ((height + tileHeight - 1) / tileHeight);
|
||||
if ((minTilesX & 1) == 1) minTilesX++;
|
||||
if ((minTilesY & 1) == 1) minTilesY++;
|
||||
tilesX = minTilesX + 3; // pad width comfortably
|
||||
tilesY = minTilesY + 7; // pad height for lower walls / upper walls
|
||||
renderWidth = tilesX * tileWidth;
|
||||
renderHeight = tilesY * tileHeight;
|
||||
assert (tilesX & 1) == 1 && (tilesY & 1) == 1;
|
||||
}
|
||||
|
||||
// TODO: render will overscan image in y-axis to accommodate walls, should change to wall only instead of entire frame
|
||||
public void render(PaletteIndexedBatch batch) {
|
||||
for (int i = 0, x, y; i < DS1.MAX_LAYERS; i++) {
|
||||
int startX2 = startX;
|
||||
int startY2 = startY;
|
||||
int startPx2 = startPx;
|
||||
int startPy2 = startPy;
|
||||
for (y = 0; y < viewBuffer.length; y++) {
|
||||
int dx = startX2;
|
||||
int dy = startY2;
|
||||
int px = startPx2;
|
||||
int py = startPy2;
|
||||
int size = viewBuffer[y];
|
||||
for (x = 0; x < size; x++) {
|
||||
Map.Zone zone = map.getZone(dx, dy);
|
||||
if (zone != null) {
|
||||
//Map.Tile[][] tiles = zone.tiles[i];
|
||||
//if (tiles != null) {
|
||||
Map.Tile tile = zone.get(i, dx, dy);
|
||||
switch (i) {
|
||||
case 0:
|
||||
case 1:
|
||||
//drawWalls(batch, tile, px, py, false);
|
||||
drawFloors(batch, tile, px, py);
|
||||
//batch.setBlendMode(BlendMode.SHADOW, SHADOW_TINT);
|
||||
//drawShadows(batch, dx, dy, px, py);
|
||||
//batch.resetBlendMode();
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3: case 4: case 5: case 6:
|
||||
drawWalls(batch, tile, px, py, true);
|
||||
break;
|
||||
default:
|
||||
//...
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
dx++;
|
||||
px += halfTileWidth;
|
||||
py -= halfTileHeight;
|
||||
}
|
||||
|
||||
startY2++;
|
||||
if (y >= tilesX - 1) {
|
||||
startX2++;
|
||||
startPy2 -= tileHeight;
|
||||
} else {
|
||||
startX2--;
|
||||
startPx2 -= tileWidth;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void renderDebug(ShapeRenderer shapes) {
|
||||
if (RENDER_DEBUG_GRID > 0)
|
||||
renderDebugGrid(shapes);
|
||||
|
||||
if (RENDER_DEBUG_WALKABLE > 0)
|
||||
renderDebugWalkable(shapes);
|
||||
|
||||
if (RENDER_DEBUG_TILE) {
|
||||
shapes.setColor(Color.OLIVE);
|
||||
drawDiamond(shapes, tpx, tpy, DT1.Tile.WIDTH, DT1.Tile.HEIGHT);
|
||||
}
|
||||
|
||||
if (RENDER_DEBUG_SUBTILE) {
|
||||
shapes.setColor(Color.WHITE);
|
||||
drawDiamond(shapes, spx, spy, DT1.Tile.SUBTILE_WIDTH, DT1.Tile.SUBTILE_HEIGHT);
|
||||
}
|
||||
|
||||
if (RENDER_DEBUG_CAMERA) {
|
||||
shapes.setColor(Color.GREEN);
|
||||
shapes.rect(
|
||||
camera.position.x - camera.viewportWidth / 2,
|
||||
camera.position.y - camera.viewportHeight / 2,
|
||||
camera.viewportWidth + 1, camera.viewportHeight + 1);
|
||||
}
|
||||
|
||||
if (RENDER_DEBUG_OVERSCAN) {
|
||||
shapes.setColor(Color.GRAY);
|
||||
shapes.rect(
|
||||
tpx - renderWidth / 2 + halfTileWidth,
|
||||
tpy - renderHeight / 2 + halfTileHeight,
|
||||
renderWidth, renderHeight);
|
||||
}
|
||||
}
|
||||
|
||||
public void renderDebugWalkable(ShapeRenderer shapes) {
|
||||
//if (RENDER_DEBUG_WALKABLE == DS1.MAX_LAYERS + 1) {
|
||||
// return;
|
||||
//}
|
||||
|
||||
final int[] WALKABLE_ID = {
|
||||
20, 21, 22, 23, 24,
|
||||
15, 16, 17, 18, 19,
|
||||
10, 11, 12, 13, 14,
|
||||
5, 6, 7, 8, 9,
|
||||
0, 1, 2, 3, 4
|
||||
};
|
||||
|
||||
ShapeRenderer.ShapeType shapeType = shapes.getCurrentType();
|
||||
shapes.set(ShapeRenderer.ShapeType.Filled);
|
||||
|
||||
int startX2 = startX;
|
||||
int startY2 = startY;
|
||||
int startPx2 = startPx;
|
||||
int startPy2 = startPy;
|
||||
int x, y;
|
||||
for (y = 0; y < viewBuffer.length; y++) {
|
||||
int dx = startX2;
|
||||
int dy = startY2;
|
||||
int px = startPx2;
|
||||
int py = startPy2;
|
||||
int size = viewBuffer[y];
|
||||
for (x = 0; x < size; x++) {
|
||||
Map.Zone zone = map.getZone(dx, dy);
|
||||
if (zone != null) {
|
||||
if (RENDER_DEBUG_WALKABLE == DS1.MAX_LAYERS + 1) {
|
||||
for (int sty = 0, t = 0; sty < DT1.Tile.SUBTILE_SIZE; sty++) {
|
||||
for (int stx = 0; stx < DT1.Tile.SUBTILE_SIZE; stx++, t++) {
|
||||
int flags = zone.flags[zone.getLocalX(dx) * DT1.Tile.SUBTILE_SIZE + stx][zone.getLocalY(dy) * DT1.Tile.SUBTILE_SIZE + sty] & 0xFF;
|
||||
if (flags == 0) continue;
|
||||
renderDebugWalkableTiles(shapes, px, py, t, flags);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//Map.Tile[][] tiles = zone.tiles[RENDER_DEBUG_WALKABLE - 1];
|
||||
//if (tiles != null) {
|
||||
Map.Tile tile = zone.get(RENDER_DEBUG_WALKABLE - 1, dx, dy);
|
||||
for (int t = 0; tile != null && tile.tile != null && t < DT1.Tile.NUM_SUBTILES; t++) {
|
||||
int flags = tile.tile.tileFlags[WALKABLE_ID[t]] & 0xFF;
|
||||
if (flags == 0) continue;
|
||||
renderDebugWalkableTiles(shapes, px, py, t, flags);
|
||||
}
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
||||
dx++;
|
||||
px += halfTileWidth;
|
||||
py -= halfTileHeight;
|
||||
}
|
||||
|
||||
startY2++;
|
||||
if (y >= tilesX - 1) {
|
||||
startX2++;
|
||||
startPy2 -= tileHeight;
|
||||
} else {
|
||||
startX2--;
|
||||
startPx2 -= tileWidth;
|
||||
}
|
||||
}
|
||||
|
||||
shapes.set(shapeType);
|
||||
}
|
||||
|
||||
private void renderDebugWalkableTiles(ShapeRenderer shapes, int px, int py, int t, int flags) {
|
||||
int offX = px + DT1.Tile.SUBTILE_OFFSET[t][0];
|
||||
int offY = py + DT1.Tile.SUBTILE_OFFSET[t][1];
|
||||
|
||||
shapes.setColor(Color.CORAL);
|
||||
drawDiamond(shapes, offX, offY, DT1.Tile.SUBTILE_WIDTH, DT1.Tile.SUBTILE_HEIGHT);
|
||||
|
||||
offY += halfSubTileHeight;
|
||||
|
||||
if ((flags & DT1.Tile.FLAG_BLOCK_WALK) != 0) {
|
||||
shapes.setColor(Color.FIREBRICK);
|
||||
shapes.triangle(
|
||||
offX + 16, offY,
|
||||
offX + 16, offY + 8,
|
||||
offX + 24, offY + 4);
|
||||
}
|
||||
if ((flags & DT1.Tile.FLAG_BLOCK_LIGHT_LOS) != 0) {
|
||||
shapes.setColor(Color.FOREST);
|
||||
shapes.triangle(
|
||||
offX + 16, offY,
|
||||
offX + 32, offY,
|
||||
offX + 24, offY + 4);
|
||||
}
|
||||
if ((flags & DT1.Tile.FLAG_BLOCK_JUMP) != 0) {
|
||||
shapes.setColor(Color.ROYAL);
|
||||
shapes.triangle(
|
||||
offX + 16, offY,
|
||||
offX + 32, offY,
|
||||
offX + 24, offY - 4);
|
||||
}
|
||||
if ((flags & DT1.Tile.FLAG_BLOCK_PLAYER_WALK) != 0) {
|
||||
shapes.setColor(Color.VIOLET);
|
||||
shapes.triangle(
|
||||
offX + 16, offY,
|
||||
offX + 16, offY - 8,
|
||||
offX + 24, offY - 4);
|
||||
}
|
||||
if ((flags & DT1.Tile.FLAG_BLOCK_UNKNOWN1) != 0) {
|
||||
shapes.setColor(Color.GOLD);
|
||||
shapes.triangle(
|
||||
offX + 16, offY,
|
||||
offX + 16, offY - 8,
|
||||
offX + 8, offY - 4);
|
||||
}
|
||||
if ((flags & DT1.Tile.FLAG_BLOCK_LIGHT) != 0) {
|
||||
shapes.setColor(Color.SKY);
|
||||
shapes.triangle(
|
||||
offX, offY,
|
||||
offX + 16, offY,
|
||||
offX + 8, offY - 4);
|
||||
}
|
||||
if ((flags & DT1.Tile.FLAG_BLOCK_UNKNOWN2) != 0) {
|
||||
shapes.setColor(Color.WHITE);
|
||||
shapes.triangle(
|
||||
offX, offY,
|
||||
offX + 16, offY,
|
||||
offX + 8, offY + 4);
|
||||
}
|
||||
if ((flags & DT1.Tile.FLAG_BLOCK_UNKNOWN3) != 0) {
|
||||
shapes.setColor(Color.SLATE);
|
||||
shapes.triangle(
|
||||
offX + 16, offY,
|
||||
offX + 16, offY + 8,
|
||||
offX + 8, offY + 4);
|
||||
}
|
||||
}
|
||||
|
||||
public void renderDebugGrid(ShapeRenderer shapes) {
|
||||
int x, y;
|
||||
switch (RENDER_DEBUG_GRID) {
|
||||
case 1:
|
||||
shapes.setColor(RENDER_DEBUG_GRID_COLOR_1);
|
||||
int startPx2 = startPx;
|
||||
int startPy2 = startPy;
|
||||
for (y = 0; y < viewBuffer.length; y++) {
|
||||
int px = startPx2;
|
||||
int py = startPy2;
|
||||
int size = viewBuffer[y];
|
||||
for (x = 0; x < size; x++) {
|
||||
for (int t = 0; t < DT1.Tile.NUM_SUBTILES; t++) {
|
||||
drawDiamond(shapes,
|
||||
px + DT1.Tile.SUBTILE_OFFSET[t][0], py + DT1.Tile.SUBTILE_OFFSET[t][1],
|
||||
DT1.Tile.SUBTILE_WIDTH, DT1.Tile.SUBTILE_HEIGHT);
|
||||
}
|
||||
|
||||
px += halfTileWidth;
|
||||
py -= halfTileHeight;
|
||||
}
|
||||
|
||||
if (y >= tilesX - 1) {
|
||||
startPy2 -= tileHeight;
|
||||
} else {
|
||||
startPx2 -= tileWidth;
|
||||
}
|
||||
}
|
||||
|
||||
case 2:
|
||||
shapes.setColor(RENDER_DEBUG_GRID_COLOR_2);
|
||||
startPx2 = startPx;
|
||||
startPy2 = startPy;
|
||||
for (y = 0; y < viewBuffer.length; y++) {
|
||||
int px = startPx2;
|
||||
int py = startPy2;
|
||||
int size = viewBuffer[y];
|
||||
for (x = 0; x < size; x++) {
|
||||
drawDiamond(shapes, px, py, DT1.Tile.WIDTH, DT1.Tile.HEIGHT);
|
||||
px += halfTileWidth;
|
||||
py -= halfTileHeight;
|
||||
}
|
||||
|
||||
if (y >= tilesX - 1) {
|
||||
startPy2 -= tileHeight;
|
||||
} else {
|
||||
startPx2 -= tileWidth;
|
||||
}
|
||||
}
|
||||
|
||||
case 3:
|
||||
shapes.setColor(RENDER_DEBUG_GRID_COLOR_3);
|
||||
ShapeRenderer.ShapeType shapeType = shapes.getCurrentType();
|
||||
shapes.set(ShapeRenderer.ShapeType.Filled);
|
||||
final int LINE_WIDTH = 2;
|
||||
int startX2 = startX;
|
||||
int startY2 = startY;
|
||||
startPx2 = startPx;
|
||||
startPy2 = startPy;
|
||||
for (y = 0; y < viewBuffer.length; y++) {
|
||||
int dx = startX2;
|
||||
int dy = startY2;
|
||||
int px = startPx2;
|
||||
int py = startPy2;
|
||||
int size = viewBuffer[y];
|
||||
for (x = 0; x < size; x++) {
|
||||
Map.Zone zone = map.getZone(dx, dy);
|
||||
if (zone != null) {
|
||||
int mod = dx < 0
|
||||
? (dx + 1) % zone.gridSizeX + (zone.gridSizeX - 1)
|
||||
: dx % zone.gridSizeX;
|
||||
if (mod == 0)
|
||||
shapes.rectLine(px, py + halfTileHeight, px + halfTileWidth, py + tileHeight, LINE_WIDTH);
|
||||
else if (mod == zone.gridSizeX - 1)
|
||||
shapes.rectLine(px + tileWidth, py + halfTileHeight, px + halfTileWidth, py, LINE_WIDTH);
|
||||
|
||||
mod = dy < 0
|
||||
? (dy + 1) % zone.gridSizeY + (zone.gridSizeY - 1)
|
||||
: dy % zone.gridSizeY;
|
||||
if (mod == 0)
|
||||
shapes.rectLine(px + halfTileWidth, py + tileHeight, px + tileWidth, py + halfTileHeight, LINE_WIDTH);
|
||||
else if (mod == zone.gridSizeY - 1)
|
||||
shapes.rectLine(px + halfTileWidth, py, px, py + halfTileHeight, LINE_WIDTH);
|
||||
}
|
||||
|
||||
dx++;
|
||||
px += halfTileWidth;
|
||||
py -= halfTileHeight;
|
||||
}
|
||||
|
||||
startY2++;
|
||||
if (y >= tilesX - 1) {
|
||||
startX2++;
|
||||
startPy2 -= tileHeight;
|
||||
} else {
|
||||
startX2--;
|
||||
startPx2 -= tileWidth;
|
||||
}
|
||||
}
|
||||
shapes.set(shapeType);
|
||||
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
private static void drawDiamond(ShapeRenderer shapes, float x, float y, int width, int height) {
|
||||
int hw = width >>> 1;
|
||||
int hh = height >>> 1;
|
||||
shapes.line(x , y + hh , x + hw , y + height);
|
||||
shapes.line(x + hw , y + height, x + width, y + hh );
|
||||
shapes.line(x + width, y + hh , x + hw , y );
|
||||
shapes.line(x + hw , y , x , y + hh );
|
||||
}
|
||||
|
||||
private void drawFloors(PaletteIndexedBatch batch, Map.Tile tile, int px, int py) {
|
||||
if (tile == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
batch.draw(tile.tile.texture, px, py, tile.tile.texture.getWidth() + 1, tile.tile.texture.getHeight() + 1);
|
||||
}
|
||||
|
||||
private void drawWalls(PaletteIndexedBatch batch, Map.Tile tile, int px, int py, boolean upper) {
|
||||
if (tile == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
//RENDER_DEBUG_SPECIAL
|
||||
if (Orientation.isSpecial(tile.cell.orientation)) {
|
||||
if (!RENDER_DEBUG_SPECIAL) return;
|
||||
FontTBL.BitmapFont font = Diablo.fonts.font16;
|
||||
GlyphLayout layout = new GlyphLayout(font, map.getSpecialName(tile.cell.id));
|
||||
font.draw(batch, layout,
|
||||
px + DT1.Tile.WIDTH / 2 - layout.width / 2,
|
||||
py + DT1.Tile.HEIGHT / 2 - layout.height / 2);
|
||||
return;
|
||||
}
|
||||
|
||||
if (tile.tile.orientation < Orientation.LEFT_WALL) {
|
||||
return;
|
||||
}
|
||||
|
||||
batch.draw(tile.tile.texture, px, tile.tile.orientation == Orientation.ROOF ? py + tile.tile.roofHeight : py);
|
||||
if (tile.tile.orientation == Orientation.RIGHT_NORTH_CORNER_WALL) {
|
||||
DT1.Tile sister = Diablo.dt1s.get(Orientation.LEFT_NORTH_CORNER_WALL, tile.tile.mainIndex, tile.tile.subIndex);
|
||||
batch.draw(sister.texture, px, py);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
package gdx.diablo.map2;
|
||||
|
||||
import com.badlogic.gdx.utils.async.AsyncTask;
|
||||
|
||||
public class MapZoneLoader implements AsyncTask<Void> {
|
||||
private static final String TAG = "MapZoneLoader";
|
||||
private static final boolean DEBUG = true;
|
||||
|
||||
Map map;
|
||||
|
||||
public MapZoneLoader(Map map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void call() {
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,109 +0,0 @@
|
||||
package gdx.diablo.map2;
|
||||
|
||||
public class Orientation {
|
||||
/** Floors */
|
||||
public static final int FLOOR = 0;
|
||||
/** Left Wall */
|
||||
public static final int LEFT_WALL = 1;
|
||||
/** Right Wall */
|
||||
public static final int RIGHT_WALL = 2;
|
||||
/** Right part of north corner wall */
|
||||
public static final int RIGHT_NORTH_CORNER_WALL = 3;
|
||||
/** Left part of north corner wall */
|
||||
public static final int LEFT_NORTH_CORNER_WALL = 4;
|
||||
/** Left end wall */
|
||||
public static final int LEFT_END_WALL = 5;
|
||||
/** Right end wall */
|
||||
public static final int RIGHT_END_WALL = 6;
|
||||
/** South corner wall */
|
||||
public static final int SOUTH_CORNER_WALL = 7;
|
||||
/** Left wall with door */
|
||||
public static final int LEFT_WALL_DOOR = 8;
|
||||
/** Right wall with door */
|
||||
public static final int RIGHT_WALL_DOOR = 9;
|
||||
/** Special Cell */
|
||||
public static final int SPECIAL_TILE_10 = 10;
|
||||
/** Special Cell */
|
||||
public static final int SPECIAL_TILE_11 = 11;
|
||||
/** Pillars, columns and standalone objects */
|
||||
public static final int PILLAR = 12;
|
||||
/** Shadows */
|
||||
public static final int SHADOW = 13;
|
||||
/** Trees */
|
||||
public static final int TREE = 14;
|
||||
/** Roofs */
|
||||
public static final int ROOF = 15;
|
||||
/** Lower walls equivalent to Orientation 1
|
||||
* @see #LEFT_WALL */
|
||||
public static final int LOWER_LEFT_WALL = 16;
|
||||
/** Lower walls equivalent to Orientation 2
|
||||
* @see #RIGHT_WALL */
|
||||
public static final int LOWER_RIGHT_WALL = 17;
|
||||
/** Lower walls equivalent to Orientation 3 and 4
|
||||
* @see #RIGHT_NORTH_CORNER_WALL
|
||||
* @see #LEFT_NORTH_CORNER_WALL */
|
||||
public static final int LOWER_NORTH_CORNER_WALL = 18;
|
||||
/** Lower walls equivalent to Orientation 7
|
||||
* @see #SOUTH_CORNER_WALL */
|
||||
public static final int LOWER_SOUTH_CORNER_WALL = 19;
|
||||
|
||||
public static String toString(int orientation) {
|
||||
switch (orientation) {
|
||||
case FLOOR: return "FLOOR";
|
||||
case LEFT_WALL: return "LEFT_WALL";
|
||||
case RIGHT_WALL: return "RIGHT_WALL";
|
||||
case RIGHT_NORTH_CORNER_WALL: return "RIGHT_NORTH_CORNER_WALL";
|
||||
case LEFT_NORTH_CORNER_WALL: return "LEFT_NORTH_CORNER_WALL";
|
||||
case LEFT_END_WALL: return "LEFT_END_WALL";
|
||||
case RIGHT_END_WALL: return "RIGHT_END_WALL";
|
||||
case SOUTH_CORNER_WALL: return "SOUTH_CORNER_WALL";
|
||||
case LEFT_WALL_DOOR: return "LEFT_WALL_DOOR";
|
||||
case RIGHT_WALL_DOOR: return "RIGHT_WALL_DOOR";
|
||||
case SPECIAL_TILE_10: return "SPECIAL_TILE_10";
|
||||
case SPECIAL_TILE_11: return "SPECIAL_TILE_11";
|
||||
case PILLAR: return "PILLAR";
|
||||
case SHADOW: return "SHADOW";
|
||||
case TREE: return "TREE";
|
||||
case ROOF: return "ROOF";
|
||||
case LOWER_LEFT_WALL: return "LOWER_LEFT_WALL";
|
||||
case LOWER_RIGHT_WALL: return "LOWER_RIGHT_WALL";
|
||||
case LOWER_NORTH_CORNER_WALL: return "LOWER_NORTH_CORNER_WALL";
|
||||
case LOWER_SOUTH_CORNER_WALL: return "LOWER_SOUTH_CORNER_WALL";
|
||||
default: return "null";
|
||||
}
|
||||
}
|
||||
|
||||
public static int toDirection(int orientation) {
|
||||
switch (orientation) {
|
||||
case LEFT_WALL: case LEFT_END_WALL: case LEFT_WALL_DOOR:
|
||||
return 1;
|
||||
case RIGHT_WALL: case RIGHT_END_WALL: case RIGHT_WALL_DOOR:
|
||||
return 2;
|
||||
case FLOOR: case RIGHT_NORTH_CORNER_WALL: case LEFT_NORTH_CORNER_WALL: case PILLAR: case TREE:
|
||||
return 3;
|
||||
case SOUTH_CORNER_WALL:
|
||||
return 4;
|
||||
case ROOF:
|
||||
return 5;
|
||||
case LOWER_LEFT_WALL:
|
||||
return 6;
|
||||
case LOWER_RIGHT_WALL:
|
||||
return 7;
|
||||
case LOWER_NORTH_CORNER_WALL:
|
||||
return 8;
|
||||
case LOWER_SOUTH_CORNER_WALL:
|
||||
return 9;
|
||||
default: throw new AssertionError();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isSpecial(int orientation) {
|
||||
switch (orientation) {
|
||||
case SPECIAL_TILE_10:
|
||||
case SPECIAL_TILE_11:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
7
core/src/gdx/diablo/net/Codec.java
Normal file
7
core/src/gdx/diablo/net/Codec.java
Normal file
@ -0,0 +1,7 @@
|
||||
package gdx.diablo.net;
|
||||
|
||||
public class Codec {
|
||||
|
||||
private Codec() {}
|
||||
|
||||
}
|
9
core/src/gdx/diablo/net/GameLogonPacket.java
Normal file
9
core/src/gdx/diablo/net/GameLogonPacket.java
Normal file
@ -0,0 +1,9 @@
|
||||
package gdx.diablo.net;
|
||||
|
||||
import java.io.DataInputStream;
|
||||
|
||||
public class ConnectPacket {
|
||||
ConnectPacket(DataInputStream in) {
|
||||
|
||||
}
|
||||
}
|
7
core/src/gdx/diablo/net/Packet.java
Normal file
7
core/src/gdx/diablo/net/Packet.java
Normal file
@ -0,0 +1,7 @@
|
||||
package gdx.diablo.net;
|
||||
|
||||
public class Packet {
|
||||
|
||||
private Packet() {}
|
||||
|
||||
}
|
7
core/src/gdx/diablo/net/UploadD2SPacket.java
Normal file
7
core/src/gdx/diablo/net/UploadD2SPacket.java
Normal file
@ -0,0 +1,7 @@
|
||||
package gdx.diablo.net;
|
||||
|
||||
public class UploadD2SPacket {
|
||||
|
||||
private UploadD2SPacket() {}
|
||||
|
||||
}
|
34
core/src/gdx/diablo/net/d2gs/WalkToEntityPacket.java
Normal file
34
core/src/gdx/diablo/net/d2gs/WalkToEntityPacket.java
Normal file
@ -0,0 +1,34 @@
|
||||
package gdx.diablo.net.d2gs;
|
||||
|
||||
import com.google.common.io.LittleEndianDataInputStream;
|
||||
import com.google.common.io.LittleEndianDataOutputStream;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import gdx.diablo.net.Codec;
|
||||
|
||||
public class WalkToLocationPacket extends Codec {
|
||||
static final int SIZE = 4;
|
||||
|
||||
public int x;
|
||||
public int y;
|
||||
|
||||
WalkToLocationPacket() {}
|
||||
|
||||
@Override
|
||||
public void encode(LittleEndianDataOutputStream out) throws IOException {
|
||||
out.writeShort(x);
|
||||
out.writeShort(y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decode(LittleEndianDataInputStream in) throws IOException {
|
||||
x = in.readUnsignedShort();
|
||||
y = in.readUnsignedShort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return x + ", " + y;
|
||||
}
|
||||
}
|
34
core/src/gdx/diablo/net/d2gs/WalkToLocationPacket.java
Normal file
34
core/src/gdx/diablo/net/d2gs/WalkToLocationPacket.java
Normal file
@ -0,0 +1,34 @@
|
||||
package gdx.diablo.net.d2gs;
|
||||
|
||||
import com.google.common.io.LittleEndianDataInputStream;
|
||||
import com.google.common.io.LittleEndianDataOutputStream;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import gdx.diablo.net.Codec;
|
||||
|
||||
public class MoveToLocationPacket extends Codec {
|
||||
static final int SIZE = 4;
|
||||
|
||||
public int x;
|
||||
public int y;
|
||||
|
||||
MoveToLocationPacket() {}
|
||||
|
||||
@Override
|
||||
public void encode(LittleEndianDataOutputStream out) throws IOException {
|
||||
out.writeShort(x);
|
||||
out.writeShort(y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decode(LittleEndianDataInputStream in) throws IOException {
|
||||
x = in.readUnsignedShort();
|
||||
y = in.readUnsignedShort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return x + ", " + y;
|
||||
}
|
||||
}
|
13
core/src/gdx/diablo/screen/CharacterProviderScreen.java
Normal file
13
core/src/gdx/diablo/screen/CharacterProviderScreen.java
Normal file
@ -0,0 +1,13 @@
|
||||
package gdx.diablo.screen;
|
||||
|
||||
import com.badlogic.gdx.ScreenAdapter;
|
||||
|
||||
import gdx.diablo.entity3.Player;
|
||||
|
||||
public abstract class CharacterScreenAdapter extends ScreenAdapter {
|
||||
|
||||
public CharacterScreenAdapter(Player player) {
|
||||
|
||||
}
|
||||
|
||||
}
|
5
core/test/gdx/diablo/net/GameLogonPacketTest.java
Normal file
5
core/test/gdx/diablo/net/GameLogonPacketTest.java
Normal file
@ -0,0 +1,5 @@
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
public class GameLogonPacketTest {
|
||||
|
||||
}
|
49
core/test/gdx/diablo/net/d2gs/WalkToEntityPacketTest.java
Normal file
49
core/test/gdx/diablo/net/d2gs/WalkToEntityPacketTest.java
Normal file
@ -0,0 +1,49 @@
|
||||
package gdx.diablo.net.d2gs;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
import gdx.diablo.util.DebugUtils;
|
||||
|
||||
public class WalkToLocationPacketTest {
|
||||
private static final int X = 0xFF;
|
||||
private static final int Y = 0xFFFF;
|
||||
private static final byte[] BYTES = new byte[]{(byte) 0xFF, 0x00, (byte) 0xFF, (byte) 0xFF};
|
||||
|
||||
@Test
|
||||
public void encode() {
|
||||
WalkToLocationPacket packet = new WalkToLocationPacket() {{
|
||||
x = X;
|
||||
y = Y;
|
||||
}};
|
||||
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream(WalkToLocationPacket.SIZE);
|
||||
try {
|
||||
packet.encode(out);
|
||||
} catch (Throwable t) {
|
||||
System.err.println(t.getMessage());
|
||||
}
|
||||
|
||||
byte[] bytes = out.toByteArray();
|
||||
System.out.println(packet + " -> " + DebugUtils.toByteArray(bytes));
|
||||
Assert.assertArrayEquals(BYTES, bytes);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void decode() {
|
||||
WalkToLocationPacket packet = new WalkToLocationPacket();
|
||||
try {
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(BYTES);
|
||||
packet.decode(in);
|
||||
} catch (Throwable t) {
|
||||
System.out.println(t.getMessage());
|
||||
}
|
||||
|
||||
System.out.println(DebugUtils.toByteArray(BYTES) + " -> " + packet);
|
||||
Assert.assertEquals(X, packet.x);
|
||||
Assert.assertEquals(Y, packet.y);
|
||||
}
|
||||
}
|
46
core/test/gdx/diablo/net/d2gs/WalkToLocationPacketTest.java
Normal file
46
core/test/gdx/diablo/net/d2gs/WalkToLocationPacketTest.java
Normal file
@ -0,0 +1,46 @@
|
||||
package gdx.diablo.net.d2gs;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
import gdx.diablo.util.DebugUtils;
|
||||
|
||||
public class MoveToLocationPacketTest {
|
||||
|
||||
@Test
|
||||
public void encode() {
|
||||
MoveToLocationPacket packet = new MoveToLocationPacket() {{
|
||||
x = 31;
|
||||
y = 63;
|
||||
}};
|
||||
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream(MoveToLocationPacket.SIZE);
|
||||
try {
|
||||
packet.encode(out);
|
||||
} catch (Throwable t) {
|
||||
System.err.println(t.getMessage());
|
||||
}
|
||||
|
||||
byte[] bytes = out.toByteArray();
|
||||
System.out.println(DebugUtils.toByteArray(bytes));
|
||||
Assert.assertArrayEquals(new byte[]{0x1F, 0x00, 0x3F, 0x00}, bytes);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void decode() {
|
||||
MoveToLocationPacket packet = new MoveToLocationPacket();
|
||||
try {
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(new byte[]{0x1F, 0x00, 0x3F, 0x00});
|
||||
packet.decode(in);
|
||||
} catch (Throwable t) {
|
||||
System.out.println(t.getMessage());
|
||||
}
|
||||
|
||||
System.out.println(packet);
|
||||
Assert.assertEquals(31, packet.x);
|
||||
Assert.assertEquals(63, packet.y);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user