New map format, completely broke loading or playing

This commit is contained in:
Anuken
2018-03-17 21:21:24 -04:00
parent 713875100b
commit 172ac78466
55 changed files with 483 additions and 2664 deletions

View File

@@ -53,6 +53,9 @@ public class Vars{
//save file directory
public static final FileHandle saveDirectory = gwt ? null : UCore.isAssets() ?
Gdx.files.local("../../desktop/mindustry-saves") : Gdx.files.local("mindustry-saves/");
public static final String mapExtension = "mmap";
public static final String saveExtension = "msav";
//scale of the font
public static float fontscale = Math.max(Unit.dp.scl(1f)/2f, 0.5f);
//camera zoom displayed on startup

View File

@@ -1,17 +1,11 @@
package io.anuke.mindustry.ai;
import com.badlogic.gdx.ai.pfa.PathFinderRequest;
import com.badlogic.gdx.ai.pfa.PathSmoother;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.math.Vector2;
import io.anuke.mindustry.entities.units.BaseUnit;
import io.anuke.mindustry.game.SpawnPoint;
import io.anuke.mindustry.world.Tile;
import io.anuke.ucore.core.Timers;
import io.anuke.ucore.util.Log;
import static io.anuke.mindustry.Vars.state;
import static io.anuke.mindustry.Vars.world;
public class Pathfind{
/**Maximum time taken per frame on pathfinding for a single path.*/
@@ -40,6 +34,7 @@ public class Pathfind{
/**Update the pathfinders and continue calculating the path if it hasn't been calculated yet.
* This method is run each frame.*/
public void update(){
/*
//go through each spawnpoint, and if it's not found a path yet, update it
for(int i = 0; i < world.getSpawns().size; i ++){
@@ -60,46 +55,20 @@ public class Pathfind{
point.request.pathFound = true;
}
}
}
}*/
}
//1300-1500ms, usually 1400 unoptimized on Caldera
/**Benchmark pathfinding speed. Debugging stuff.*/
public void benchmark(){
SpawnPoint point = world.getSpawns().first();
int amount = 100;
//warmup
for(int i = 0; i < 100; i ++){
point.finder.searchNodePath(point.start, world.getCore(), state.difficulty.heuristic, point.path);
point.path.clear();
}
Timers.mark();
for(int i = 0; i < amount; i ++){
point.finder.searchNodePath(point.start, world.getCore(), state.difficulty.heuristic, point.path);
point.path.clear();
}
Log.info("Time elapsed: {0}ms\nAverage MS per path: {1}", Timers.elapsed(), Timers.elapsed()/amount);
}
/**Reset and clear the paths.*/
public void resetPaths(){
for(int i = 0; i < world.getSpawns().size; i ++){
resetPathFor(world.getSpawns().get(i));
}
}
private void resetPathFor(SpawnPoint point){
/*
point.finder = new OptimizedPathFinder<>(graph);
point.path.clear();
point.pathTiles = null;
//TODO
point.request = new PathFinderRequest<>(point.start, world.getCore(), state.difficulty.heuristic, point.path);
point.request.statusChanged = true; //IMPORTANT!
point.request.statusChanged = true; //IMPORTANT!*/
}
/**Finds the closest tile to a position, in an array of tiles.*/

View File

@@ -9,25 +9,26 @@ import io.anuke.mindustry.game.EventType.*;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.game.Tutorial;
import io.anuke.mindustry.game.UpgradeInventory;
import io.anuke.mindustry.graphics.Fx;
import io.anuke.mindustry.input.AndroidInput;
import io.anuke.mindustry.input.DefaultKeybinds;
import io.anuke.mindustry.input.DesktopInput;
import io.anuke.mindustry.input.InputHandler;
import io.anuke.mindustry.io.Map;
import io.anuke.mindustry.io.Platform;
import io.anuke.mindustry.io.Saves;
import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.resource.Item;
import io.anuke.mindustry.resource.Mech;
import io.anuke.mindustry.resource.Weapon;
import io.anuke.mindustry.world.Map;
import io.anuke.ucore.UCore;
import io.anuke.ucore.core.*;
import io.anuke.ucore.core.Inputs.DeviceType;
import io.anuke.ucore.entities.Entities;
import io.anuke.ucore.modules.Module;
import io.anuke.ucore.scene.ui.layout.Unit;
import io.anuke.ucore.util.*;
import io.anuke.ucore.util.Atlas;
import io.anuke.ucore.util.InputProxy;
import io.anuke.ucore.util.Mathf;
import static io.anuke.mindustry.Vars.*;
@@ -126,10 +127,6 @@ public class Control extends Module{
KeyBinds.load();
for(Map map : world.maps().list()){
Settings.defaults("hiscore" + map.name, 0);
}
player = new Player();
player.name = Settings.getString("name");
player.mech = android ? Mech.standardShip : Mech.standard;
@@ -188,11 +185,15 @@ public class Control extends Module{
Events.on(GameOverEvent.class, () -> {
Effects.shake(5, 6, Core.camera.position.x, Core.camera.position.y);
Sounds.play("corexplode");
//TODO effects???
//Sounds.play("corexplode");
/*
for(int i = 0; i < 16; i ++){
Timers.run(i*2, ()-> Effects.effect(Fx.explosion, world.getCore().worldx()+Mathf.range(40), world.getCore().worldy()+Mathf.range(40)));
}
Effects.effect(Fx.coreexplosion, world.getCore().worldx(), world.getCore().worldy());
Effects.effect(Fx.coreexplosion, world.getCore().worldx(), world.getCore().worldy());*/
ui.restart.show();
@@ -249,23 +250,6 @@ public class Control extends Module{
return tutorial;
}
private void checkOldUser(){
boolean hasPlayed = false;
for(Map map : world.maps().getAllMaps()){
if(Settings.getInt("hiscore" + map.name) != 0){
hasPlayed = true;
break;
}
}
if(hasPlayed && Settings.getString("lastVersion").equals("3.2")){
Timers.runTask(1f, () -> ui.showInfo("$text.changes"));
Settings.putString("lastVersion", "3.3");
Settings.save();
}
}
@Override
public void dispose(){
Platform.instance.onGameExit();
@@ -292,8 +276,6 @@ public class Control extends Module{
Entities.initPhysics();
Platform.instance.updateRPC();
checkOldUser();
}
@Override

View File

@@ -14,7 +14,6 @@ public class GameState{
public final Inventory inventory = new Inventory();
public int wave = 1;
public int lastUpdated = -1;
public float wavetime;
public float extrawavetime;
public int enemies = 0;

View File

@@ -11,7 +11,6 @@ import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.game.WaveCreator;
import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.net.NetEvents;
import io.anuke.mindustry.world.blocks.ProductionBlocks;
import io.anuke.ucore.core.Events;
import io.anuke.ucore.core.Timers;
import io.anuke.ucore.entities.Entities;
@@ -51,7 +50,6 @@ public class Logic extends Module {
state.extrawavetime = maxwavespace * state.difficulty.maxTimeScaling;
state.wavetime = wavespace * state.difficulty.timeScaling;
state.enemies = 0;
state.lastUpdated = -1;
state.gameOver = false;
state.inventory.clearItems();
state.allyTeams.clear();
@@ -67,11 +65,6 @@ public class Logic extends Module {
public void runWave(){
if(state.lastUpdated < state.wave + 1){
world.pathfinder().resetPaths();
state.lastUpdated = state.wave + 1;
}
//TODO spawn enemies
state.wave ++;
@@ -93,7 +86,7 @@ public class Logic extends Module {
if(!Net.client())
world.pathfinder().update();
if(world.getCore() != null && world.getCore().block() != ProductionBlocks.core && !state.gameOver){
if(world.getAllyCores().size == 0 && !state.gameOver){
state.gameOver = true;
if(Net.server()) NetEvents.handleGameOver();
Events.fire(GameOverEvent.class);
@@ -105,11 +98,6 @@ public class Logic extends Module {
if(state.enemies <= 0){
if(!world.getMap().name.equals("tutorial")) state.wavetime -= delta();
if(state.lastUpdated < state.wave + 1 && state.wavetime < aheadPathfinding){ //start updating beforehand
world.pathfinder().resetPaths();
state.lastUpdated = state.wave + 1;
}
}else{
state.extrawavetime -= delta();
}

View File

@@ -14,10 +14,8 @@ import io.anuke.mindustry.net.Net.SendMode;
import io.anuke.mindustry.net.NetworkIO;
import io.anuke.mindustry.net.Packets.*;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Map;
import io.anuke.mindustry.world.Placement;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.ProductionBlocks;
import io.anuke.ucore.core.Timers;
import io.anuke.ucore.entities.BaseBulletType;
import io.anuke.ucore.entities.Entities;
@@ -101,18 +99,6 @@ public class NetClient extends Module {
finishConnecting();
});
Net.handleClient(CustomMapPacket.class, packet -> {
Log.info("Recieved custom map: {0} bytes.", packet.stream.available());
//custom map is always sent before world data
Map map = NetworkIO.loadMap(packet.stream);
world.maps().setNetworkMap(map);
MapAckPacket ack = new MapAckPacket();
Net.send(ack, SendMode.tcp);
});
Net.handleClient(SyncPacket.class, packet -> {
if (connecting) return;
int players = 0;
@@ -253,10 +239,7 @@ public class NetClient extends Module {
});
Net.handleClient(GameOverPacket.class, packet -> {
if(world.getCore().block() != ProductionBlocks.core &&
world.getCore().entity != null){
world.getCore().entity.onDeath(true);
}
//TODO core death effects
quiet = true;
ui.restart.show();
});

View File

@@ -97,25 +97,7 @@ public class NetServer extends Module{
admins.getTrace(ip).playerid = player.id;
if(world.getMap().custom){
ByteArrayOutputStream stream = new ByteArrayOutputStream();
NetworkIO.writeMap(world.getMap(), stream);
CustomMapPacket data = new CustomMapPacket();
data.stream = new ByteArrayInputStream(stream.toByteArray());
Net.sendStream(id, data);
Log.info("Sending custom map: Packed {0} uncompressed bytes of MAP data.", stream.size());
}else{
//hack-- simulate the map ack packet recieved to send the world data to the client.
Net.handleServerReceived(id, new MapAckPacket());
}
Platform.instance.updateRPC();
});
Net.handleServer(MapAckPacket.class, (id, packet) -> {
Player player = connections.get(id);
//TODO try DeflaterOutputStream
ByteArrayOutputStream stream = new ByteArrayOutputStream();
NetworkIO.writeWorld(player, weapons.get(player.name, new ByteArray()), stream);
WorldData data = new WorldData();
@@ -123,6 +105,8 @@ public class NetServer extends Module{
Net.sendStream(id, data);
Log.info("Packed {0} uncompressed bytes of WORLD data.", stream.size());
Platform.instance.updateRPC();
});
Net.handleServer(ConnectConfirmPacket.class, (id, packet) -> {

View File

@@ -16,7 +16,6 @@ import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.entities.SyncEntity;
import io.anuke.mindustry.entities.units.BaseUnit;
import io.anuke.mindustry.game.SpawnPoint;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.graphics.BlockRenderer;
import io.anuke.mindustry.graphics.Shaders;
@@ -26,7 +25,6 @@ import io.anuke.mindustry.ui.fragments.ToolFragment;
import io.anuke.mindustry.world.BlockBar;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.Blocks;
import io.anuke.mindustry.world.blocks.ProductionBlocks;
import io.anuke.ucore.core.*;
import io.anuke.ucore.entities.EffectEntity;
import io.anuke.ucore.entities.Entities;
@@ -119,14 +117,11 @@ public class Renderer extends RendererModule{
}else{
boolean smoothcam = Settings.getBool("smoothcam");
if(world.getCore() == null || world.getCore().block() == ProductionBlocks.core){
if(!smoothcam){
setCamera(player.x, player.y);
}else{
smoothCamera(player.x, player.y, android ? 0.3f : 0.14f);
}
if(!smoothcam){
setCamera(player.x, player.y);
}else{
smoothCamera(world.getCore().worldx(), world.getCore().worldy(), 0.4f);
smoothCamera(player.x, player.y, android ? 0.3f : 0.14f);
}
if(Settings.getBool("pixelate"))
@@ -392,6 +387,8 @@ public class Renderer extends RendererModule{
//draw tutorial placement point
if(world.getMap().name.equals("tutorial") && control.tutorial().showBlock()){
//TODO draw placement point for tutorial
/*
int x = world.getCore().x + control.tutorial().getPlacePoint().x;
int y = world.getCore().y + control.tutorial().getPlacePoint().y;
int rot = control.tutorial().getPlaceRotation();
@@ -405,7 +402,7 @@ public class Renderer extends RendererModule{
if(rot != -1){
Lines.lineAngle(x * tilesize, y * tilesize, rot * 90, 6);
}
Draw.reset();
Draw.reset();*/
}
//draw config selected block
@@ -435,17 +432,6 @@ public class Renderer extends RendererModule{
input.placeMode.draw(control.input().getBlockX(), control.input().getBlockY(),
control.input().getBlockEndX(), control.input().getBlockEndY());
Lines.stroke(1f);
Draw.color(Color.SCARLET);
for(SpawnPoint spawn : world.getSpawns()){
Lines.dashCircle(spawn.start.worldx(), spawn.start.worldy(), enemyspawnspace);
}
if(world.getCore() != null) {
Draw.color(Color.LIME);
Lines.poly(world.getSpawnX(), world.getSpawnY(), 4, 6f, Timers.time() * 2f);
}
if(input.breakMode == PlaceMode.holdDelete)
input.breakMode.draw(tilex, tiley, 0, 0);

View File

@@ -8,7 +8,6 @@ import com.badlogic.gdx.math.Interpolation;
import com.badlogic.gdx.utils.Align;
import io.anuke.mindustry.Vars;
import io.anuke.mindustry.io.Platform;
import io.anuke.mindustry.mapeditor.MapEditorDialog;
import io.anuke.mindustry.ui.dialogs.*;
import io.anuke.mindustry.ui.fragments.*;
import io.anuke.ucore.core.Core;
@@ -44,7 +43,7 @@ public class UI extends SceneModule{
public PausedDialog paused;
public SettingsMenuDialog settings;
public ControlsDialog controls;
public MapEditorDialog editor;
public FloatingDialog editor; //TODO change back to map editor dialog
public LanguageDialog language;
public BansDialog bans;
public AdminsDialog admins;
@@ -144,7 +143,7 @@ public class UI extends SceneModule{
@Override
public void init(){
editor = new MapEditorDialog();
(editor = new FloatingDialog("The editor is currently broken.")).addCloseButton();
controls = new ControlsDialog();
restart = new RestartDialog();
join = new JoinDialog();

View File

@@ -6,20 +6,19 @@ import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array;
import io.anuke.mindustry.ai.Pathfind;
import io.anuke.mindustry.entities.TileEntity;
import io.anuke.mindustry.game.SpawnPoint;
import io.anuke.mindustry.io.Map;
import io.anuke.mindustry.io.Maps;
import io.anuke.mindustry.world.*;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.WorldGenerator;
import io.anuke.mindustry.world.blocks.Blocks;
import io.anuke.mindustry.world.blocks.DistributionBlocks;
import io.anuke.mindustry.world.blocks.ProductionBlocks;
import io.anuke.mindustry.world.blocks.WeaponBlocks;
import io.anuke.ucore.entities.Entities;
import io.anuke.ucore.entities.Entity;
import io.anuke.ucore.modules.Module;
import io.anuke.ucore.util.Mathf;
import io.anuke.ucore.util.Tmp;
import static io.anuke.mindustry.Vars.control;
import static io.anuke.mindustry.Vars.tilesize;
public class World extends Module{
@@ -31,42 +30,41 @@ public class World extends Module{
private Maps maps = new Maps();
private Array<Tile> allyCores = new Array<>();
private Array<Tile> enemyCores = new Array<>();
private Array<SpawnPoint> spawns = new Array<>();
private Array<Tile> tempTiles = new Array<>();
public World(){
maps.loadMaps();
currentMap = maps.getMap(0);
maps.load();
}
@Override
public void dispose(){
maps.dispose();
}
public Array<SpawnPoint> getSpawns(){
return spawns;
}
public Tile getCore(){
return core;
}
public Maps maps(){
return maps;
}
public Pathfind pathfinder(){
return pathfind;
}
public Array<Tile> getAllyCores() {
return allyCores;
}
public Array<Tile> getEnemyCores() {
return enemyCores;
}
//TODO proper spawnpoints!
public float getSpawnX(){
return core.worldx();
return width() * tilesize/2f;
}
public float getSpawnY(){
return core.worldy() - tilesize*2;
return height() * tilesize/2f;
}
public boolean solid(int x, int y){
@@ -105,11 +103,11 @@ public class World extends Module{
}
public int width(){
return currentMap.getWidth();
return currentMap.meta.width;
}
public int height(){
return currentMap.getHeight();
return currentMap.meta.height;
}
public Tile tile(int packed){
@@ -136,16 +134,6 @@ public class World extends Module{
return tiles;
}
private void createTiles(){
for(int x = 0; x < tiles.length; x ++){
for(int y = 0; y < tiles[0].length; y ++){
if(tiles[x][y] == null){
tiles[x][y] = new Tile(x, y, Blocks.stone);
}
}
}
}
private void clearTileEntities(){
for(int x = 0; x < tiles.length; x ++){
for(int y = 0; y < tiles[0].length; y ++){
@@ -155,43 +143,40 @@ public class World extends Module{
}
}
}
/**Resizes the tile array to the specified size and returns the resulting tile array.
* Only use for loading saves!*/
public Tile[][] createTiles(int width, int height){
if(tiles != null){
clearTileEntities();
if(tiles.length != width || tiles[0].length != height){
tiles = new Tile[width][height];
}
}else{
tiles = new Tile[width][height];
}
return tiles;
}
public void loadMap(Map map){
loadMap(map, MathUtils.random(0, 99999));
loadMap(map, MathUtils.random(0, 999999));
}
public void loadMap(Map map, int seed){
currentMap = map;
if(tiles != null){
clearTileEntities();
if(tiles.length != map.getWidth() || tiles[0].length != map.getHeight()){
tiles = new Tile[map.getWidth()][map.getHeight()];
}
createTiles();
}else{
tiles = new Tile[map.getWidth()][map.getHeight()];
createTiles();
}
spawns.clear();
Entities.resizeTree(0, 0, map.getWidth() * tilesize, map.getHeight() * tilesize);
this.currentMap = map;
this.seed = seed;
core = WorldGenerator.generate(map.pixmap, tiles, spawns);
Placement.placeBlock(core.x, core.y, ProductionBlocks.core, 0, false, false);
control.tutorial().setDefaultBlocks(core.x, core.y);
int width = map.meta.width, height = map.meta.height;
pathfind.resetPaths();
createTiles(width, height);
Entities.resizeTree(0, 0, width * tilesize, height * tilesize);
WorldGenerator.generate(tiles, maps.readTileData(map));
}
void set(int x, int y, Block type, int rot){
if(!Mathf.inBounds(x, y, tiles)){
return;
@@ -201,7 +186,7 @@ public class World extends Module{
}
tiles[x][y].setBlock(type, rot);
}
public int getSeed(){
return seed;
}

View File

@@ -3,17 +3,31 @@ package io.anuke.mindustry.entities;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.world.Tile;
import io.anuke.ucore.entities.BulletEntity;
import io.anuke.ucore.entities.Entity;
import io.anuke.ucore.util.Timer;
import static io.anuke.mindustry.Vars.*;
public class Bullet extends BulletEntity{
public Timer timer = new Timer(3);
public Team team;
public Bullet(BulletType type, Unit owner, float x, float y, float angle){
super(type, owner, angle);
set(x, y);
this.type = type;
this.team = owner.team;
set(x, y);
}
public Bullet(BulletType type, Entity owner, Team team, float x, float y, float angle){
super(type, owner, angle);
this.team = team;
this.type = type;
set(x, y);
}
public Bullet(BulletType type, Bullet parent, float x, float y, float angle){
this(type, parent.owner, parent.team, x, y, angle);
}
public void draw(){
@@ -39,14 +53,6 @@ public class Bullet extends BulletEntity{
return true;
}
public Unit owner(){
return (Unit)owner;
}
public Team team(){
return ((Unit)owner).team;
}
@Override
public void update(){
super.update();
@@ -58,7 +64,7 @@ public class Bullet extends BulletEntity{
if (tile == null) return false;
tile = tile.target();
if (tile.entity != null && tile.entity.collide(this) && !tile.entity.dead && tile.entity.tile.getTeam() != team()) {
if (tile.entity != null && tile.entity.collide(this) && !tile.entity.dead && tile.entity.tile.getTeam() != team) {
tile.entity.collision(this);
remove();
type.hit(this);

View File

@@ -121,7 +121,7 @@ public abstract class BulletType extends BaseBulletType<Bullet>{
Effects.effect(Fx.shellsmoke, b);
Effects.effect(Fx.shellexplosion, b);
DamageArea.damage(b.team(), b.x, b.y, 25f, (int)(damage * 2f/3f));
DamageArea.damage(b.team, b.x, b.y, 25f, (int)(damage * 2f/3f));
}
},
flak = new BulletType(2.9f, 8) {
@@ -148,7 +148,7 @@ public abstract class BulletType extends BaseBulletType<Bullet>{
public void hit(Bullet b, float hitx, float hity) {
Effects.effect(shellsmoke, b);
for(int i = 0; i < 3; i ++){
Bullet bullet = new Bullet(flakspark, b.owner(), hitx, hity, b.angle() + Mathf.range(120f));
Bullet bullet = new Bullet(flakspark, b, hitx, hity, b.angle() + Mathf.range(120f));
bullet.add();
}
}
@@ -201,7 +201,7 @@ public abstract class BulletType extends BaseBulletType<Bullet>{
Effects.effect(Fx.shellsmoke, b);
Effects.effect(Fx.shockwaveSmall, b);
DamageArea.damage(b.team(), b.x, b.y, 50f, (int)(damage * 2f/3f));
DamageArea.damage(b.team, b.x, b.y, 50f, (int)(damage * 2f/3f));
}
},
yellowshell = new BulletType(1.2f, 20){
@@ -232,7 +232,7 @@ public abstract class BulletType extends BaseBulletType<Bullet>{
Effects.effect(Fx.shellsmoke, b);
Effects.effect(Fx.shockwaveSmall, b);
DamageArea.damage(b.team(), b.x, b.y, 25f, (int)(damage * 2f/3f));
DamageArea.damage(b.team, b.x, b.y, 25f, (int)(damage * 2f/3f));
}
},
blast = new BulletType(1.1f, 90){
@@ -255,7 +255,7 @@ public abstract class BulletType extends BaseBulletType<Bullet>{
//TODO remove translation() usage
Angles.circleVectors(30, 6f, (nx, ny) -> {
float ang = Mathf.atan2(nx, ny);
Bullet o = new Bullet(blastshot, b.owner(), b.x + nx, b.y + ny, ang).add();
Bullet o = new Bullet(blastshot, b, b.x + nx, b.y + ny, ang).add();
o.damage = b.damage/9;
});
}
@@ -370,7 +370,7 @@ public abstract class BulletType extends BaseBulletType<Bullet>{
Effects.effect(Fx.clusterbomb, b);
DamageArea.damage(b.team(), b.x, b.y, 35f, damage);
DamageArea.damage(b.team, b.x, b.y, 35f, damage);
}
},
vulcan = new BulletType(4.5f, 12) {
@@ -419,7 +419,7 @@ public abstract class BulletType extends BaseBulletType<Bullet>{
public void hit(Bullet b, float hitx, float hity) {
for(int i = 0; i < 4; i ++){
Bullet bullet = new Bullet(scrap, b.owner(), b.x, b.y, b.angle() + Mathf.range(80f));
Bullet bullet = new Bullet(scrap, b, b.x, b.y, b.angle() + Mathf.range(80f));
bullet.add();
}
}
@@ -449,7 +449,7 @@ public abstract class BulletType extends BaseBulletType<Bullet>{
}
public void init(Bullet b) {
DamageArea.damageLine(b.team(), Fx.beamhit, b.x, b.y, b.angle(), length, damage);
DamageArea.damageLine(b.team, Fx.beamhit, b.x, b.y, b.angle(), length, damage);
}
public void draw(Bullet b) {

View File

@@ -4,7 +4,6 @@ import com.badlogic.gdx.math.GridPoint2;
import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.resource.Item;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.*;
import io.anuke.ucore.core.Timers;
import io.anuke.ucore.scene.builders.button;
@@ -70,11 +69,12 @@ public class Tutorial{
//info.setText(stage.text);
if(stage.showBlock){
/*
Tile tile = world.tile(world.getCore().x + stage.blockPlaceX, world.getCore().y + stage.blockPlaceY);
if(tile.block() == stage.targetBlock && (tile.getRotation() == stage.blockRotation || stage.blockRotation == -1)){
move(true);
}
}*/
}
}
@@ -287,6 +287,7 @@ public class Tutorial{
}
void onSwitch(){
/*
for(int flip : new int[]{1, -1}){
world.tile(world.getCore().x + flip, world.getCore().y - 2).setBlock(DistributionBlocks.conveyor, 2 * flip);
world.tile(world.getCore().x + flip*2, world.getCore().y - 2).setBlock(DistributionBlocks.conveyor, 2 * flip);
@@ -295,7 +296,7 @@ public class Tutorial{
world.tile(world.getCore().x + flip*2, world.getCore().y - 4).setFloor(Blocks.stone);
world.tile(world.getCore().x + flip*2, world.getCore().y - 4).setBlock(ProductionBlocks.stonedrill);
}
}*/
}
},
deleteBlock{
@@ -342,7 +343,7 @@ public class Tutorial{
void onSwitch(){
for(int i = 0; i < 4; i ++){
world.tile(world.getCore().x + 2, world.getCore().y - 2 + i).setBlock(DistributionBlocks.conveyor, 1);
//world.tile(world.getCore().x + 2, world.getCore().y - 2 + i).setBlock(DistributionBlocks.conveyor, 1);
}
control.input().recipe = null;
@@ -428,7 +429,7 @@ public class Tutorial{
void onSwitch(){
ui.<ImageButton>find("sectionbuttondistribution").fireClick();
world.tile(blockPlaceX + world.getCore().x, blockPlaceY + world.getCore().y).setBlock(Blocks.air);
//world.tile(blockPlaceX + world.getCore().x, blockPlaceY + world.getCore().y).setBlock(Blocks.air);
}
},
conduitUse2{
@@ -444,7 +445,7 @@ public class Tutorial{
}
void onSwitch(){
world.tile(blockPlaceX + world.getCore().x, blockPlaceY + world.getCore().y).setBlock(Blocks.air);
//world.tile(blockPlaceX + world.getCore().x, blockPlaceY + world.getCore().y).setBlock(Blocks.air);
}
},
conduitUse3{
@@ -460,7 +461,7 @@ public class Tutorial{
}
void onSwitch(){
world.tile(blockPlaceX + world.getCore().x, blockPlaceY + world.getCore().y).setBlock(Blocks.air);
//world.tile(blockPlaceX + world.getCore().x, blockPlaceY + world.getCore().y).setBlock(Blocks.air);
}
},
generator{
@@ -475,7 +476,7 @@ public class Tutorial{
}
void onSwitch(){
world.tile(blockPlaceX + world.getCore().x, blockPlaceY + world.getCore().y).setBlock(Blocks.air);
//world.tile(blockPlaceX + world.getCore().x, blockPlaceY + world.getCore().y).setBlock(Blocks.air);
ui.<ImageButton>find("sectionbuttonpower").fireClick();
state.inventory.addItem(Item.steel, 60);
state.inventory.addItem(Item.iron, 60);
@@ -558,6 +559,7 @@ public class Tutorial{
}
void onSwitch(){
/*
for(int i = 0; i < 5; i ++){
world.tile(world.getCore().x, world.getCore().y - 6 + i).setBlock(DistributionBlocks.conveyor, 1);
}
@@ -570,7 +572,7 @@ public class Tutorial{
world.tile(world.getCore().x-1, world.getCore().y - 8).setBlock(ProductionBlocks.coaldrill);
world.tile(world.getCore().x+1, world.getCore().y - 7).setBlock(DistributionBlocks.conveyor, 2);
world.tile(world.getCore().x-1, world.getCore().y - 7).setBlock(DistributionBlocks.conveyor, 0);
world.tile(world.getCore().x-1, world.getCore().y - 7).setBlock(DistributionBlocks.conveyor, 0);*/
}
},
tunnelExplain{

View File

@@ -5,7 +5,6 @@ import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.utils.Array;
import io.anuke.mindustry.game.SpawnPoint;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Layer;
import io.anuke.mindustry.world.Tile;
@@ -188,10 +187,6 @@ public class BlockRenderer{
Graphics.begin();
Draw.reset();
if(showPaths && debug){
drawPaths();
}
if(debug && debugChunks){
Draw.color(Color.YELLOW);
@@ -209,21 +204,6 @@ public class BlockRenderer{
Draw.reset();
}
}
void drawPaths(){
Draw.color(Color.RED);
for(SpawnPoint point : world.getSpawns()){
if(point.pathTiles != null){
for(int i = 1; i < point.pathTiles.length; i ++){
Lines.line(point.pathTiles[i-1].worldx(), point.pathTiles[i-1].worldy(),
point.pathTiles[i].worldx(), point.pathTiles[i].worldy());
Lines.circle(point.pathTiles[i-1].worldx(), point.pathTiles[i-1].worldy(), 6f);
}
}
}
Draw.reset();
}
void drawCache(DrawLayer layer, int crangex, int crangey){
Gdx.gl.glEnable(GL20.GL_BLEND);

View File

@@ -78,13 +78,13 @@ public abstract class InputHandler extends InputAdapter{
if(!type.isMultiblock() && control.tutorial().active() &&
control.tutorial().showBlock()){
//TODO placepoint control, make sure it's correct.
GridPoint2 point = control.tutorial().getPlacePoint();
int rotation = control.tutorial().getPlaceRotation();
Block block = control.tutorial().getPlaceBlock();
if(type != block || point.x != x - world.getCore().x || point.y != y - world.getCore().y
|| (rotation != -1 && rotation != this.rotation)){
if(type != block || (rotation != -1 && rotation != this.rotation)){
return false;
}
}else if(control.tutorial().active()){
@@ -98,11 +98,12 @@ public abstract class InputHandler extends InputAdapter{
if(control.tutorial().active()){
if(control.tutorial().showBlock()){
//TODO placepoint control, make sure it's correct
GridPoint2 point = control.tutorial().getPlacePoint();
int rotation = control.tutorial().getPlaceRotation();
Block block = control.tutorial().getPlaceBlock();
if(block != Blocks.air || point.x != x - world.getCore().x || point.y != y - world.getCore().y
if(block != Blocks.air
|| (rotation != -1 && rotation != this.rotation)){
return false;
}

View File

@@ -0,0 +1,20 @@
package io.anuke.mindustry.io;
import com.badlogic.gdx.graphics.Texture;
public class Map {
/**Internal map name. This is the filename, without any extensions.*/
public final String name;
/**Whether this is a custom map.*/
public final boolean custom;
/**Metadata. Author description, display name, etc.*/
public final MapMeta meta;
/**Preview texture.*/
public Texture texture;
public Map(String name, MapMeta meta, boolean custom){
this.name = name;
this.custom = custom;
this.meta = meta;
}
}

View File

@@ -3,4 +3,6 @@ package io.anuke.mindustry.io;
/**Reads and writes map files.*/
public class MapIO {
//TODO implementation
}

View File

@@ -0,0 +1,32 @@
package io.anuke.mindustry.io;
import com.badlogic.gdx.utils.ObjectMap;
public class MapMeta {
public final int version;
public final ObjectMap<String, String> tags;
public final int width, height;
public MapMeta(int version, ObjectMap<String, String> tags, int width, int height) {
this.version = version;
this.tags = tags;
this.width = width;
this.height = height;
}
public String author(){
return tags.get("author", "unknown");
}
public String description(){
return tags.get("description", "unknown");
}
public String name(){
return tags.get("name", "unknown");
}
public boolean hasOreGen(){
return tags.get("oregen", "1").equals("1");
}
}

View File

@@ -0,0 +1,75 @@
package io.anuke.mindustry.io;
import io.anuke.ucore.util.Bits;
import java.nio.ByteBuffer;
public class MapTileData {
/**Tile size: 3 bytes.
* 0: ground tile
* 1: wall tile
* 2: rotation + team*/
private final static int TILE_SIZE = 3;
private final ByteBuffer buffer;
private final TileData tile = new TileData();
private final int width, height;
public MapTileData(int width, int height){
this.width = width;
this.height = height;
buffer = ByteBuffer.allocate(width * height * TILE_SIZE);
}
public MapTileData(byte[] bytes, int width, int height){
buffer = ByteBuffer.wrap(bytes);
this.width = width;
this.height = height;
}
public int width(){
return width;
}
public int height(){
return height;
}
/**Reads and returns the next tile data.*/
public TileData read(){
tile.read();
return tile;
}
/**Writes tile data at a specified position. Uses the tile data returned by read().*/
public void write(int x, int y){
position(x, y);
tile.write();
}
/**Sets read position to the specified coordinates*/
public void position(int x, int y){
buffer.position((x + width * y) * TILE_SIZE);
}
public class TileData{
public byte floor, wall;
public byte rotation;
public byte team;
private void read(){
floor = buffer.get();
wall = buffer.get();
byte rt = buffer.get();
rotation = Bits.getLeftByte(rt);
team = Bits.getRightByte(rt);
}
private void write(){
buffer.put(floor);
buffer.put(wall);
byte rt = Bits.packByte(rotation, team);
buffer.put(rt);
}
}
}

View File

@@ -1,224 +1,89 @@
package io.anuke.mindustry.io;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.utils.*;
import com.badlogic.gdx.utils.Json.Serializer;
import com.badlogic.gdx.utils.JsonWriter.OutputType;
import io.anuke.mindustry.world.Map;
import io.anuke.ucore.core.Settings;
import io.anuke.ucore.graphics.Pixmaps;
import io.anuke.ucore.util.Log;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.Disposable;
import com.badlogic.gdx.utils.ObjectMap;
import static io.anuke.mindustry.Vars.*;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import static io.anuke.mindustry.Vars.customMapDirectory;
import static io.anuke.mindustry.Vars.mapExtension;
public class Maps implements Disposable{
private IntMap<Map> maps = new IntMap<>();
private ObjectMap<String, Map> mapNames = new ObjectMap<>();
private ObjectMap<String, Map> maps = new ObjectMap<>();
private Array<Map> allMaps = new Array<>();
private Array<Map> customMaps = new Array<>();
private Array<Map> defaultMaps = new Array<>();
private Map networkMap;
private int lastID;
private Json json = new Json();
private Array<Map> array = new Array<>();
public Maps() {
json.setOutputType(OutputType.json);
json.setElementType(ArrayContainer.class, "maps", Map.class);
json.setSerializer(Color.class, new ColorSerializer());
public void load(){
//TODO
}
public Iterable<Map> list(){
return maps.values();
public void save(){
//TODO?
}
public Array<Map> getDefaultMaps(){
return defaultMaps;
/**Returns a list of all maps, including custom ones.*/
public Array<Map> all(){
return allMaps;
}
public Array<Map> getCustomMaps(){
array.clear();
for(Map map : list()){
if(map.custom) array.add(map);
}
return array;
/**Returns map by internal name.*/
public Map getByName(String name){
return maps.get(name);
}
public Array<Map> getAllMaps(){
array.clear();
for(Map map : list()){
array.add(map);
}
return array;
}
public void setNetworkMap(Map map){
if(networkMap != null){
networkMap.pixmap.dispose();
networkMap = null;
}
networkMap = map;
}
public Map getMap(int id){
if(id == -1){
return networkMap;
}
return maps.get(id);
}
public Map getMap(String name){
return mapNames.get(name);
}
public void loadMaps(){
if(!loadMapFile(Gdx.files.internal("maps/maps.json"), true)){
throw new RuntimeException("Failed to load maps!");
}
if(!gwt) {
if (!loadMapFile(customMapDirectory.child("maps.json"), false)) {
try {
Log.info("Failed to find custom map directory.");
customMapDirectory.child("maps.json").writeString("{}", false);
} catch (Exception e) {
throw new RuntimeException("Failed to create custom map directory!");
}
}
}
}
public void removeMap(Map map){
maps.remove(map.id);
mapNames.remove(map.name);
Array<Map> out = new Array<>();
for(Map m : maps.values()){
if(m.custom){
out.add(m);
}
}
saveMaps(out, customMapDirectory.child("maps.json"));
}
public void saveAndReload(Map map, Pixmap out){
if(map.pixmap != null && out != map.pixmap && map.texture != null){
map.texture.dispose();
map.texture = new Texture(out);
}else if (out == map.pixmap){
map.texture.draw(out, 0, 0);
}
map.pixmap = out;
if(map.texture == null) map.texture = new Texture(map.pixmap);
if(map.id == -1){
if(mapNames.containsKey(map.name)){
map.id = mapNames.get(map.name).id;
}else{
map.id = ++lastID;
}
}
if(!Settings.has("hiscore" + map.name)){
Settings.defaults("hiscore" + map.name, 0);
}
saveCustomMap(map);
ui.levels.reload();
}
public void saveMaps(Array<Map> array, FileHandle file){
json.toJson(new ArrayContainer(array), file);
}
public void saveCustomMap(Map toSave){
toSave.custom = true;
Array<Map> out = new Array<>();
boolean added = false;
for(Map map : maps.values()){
if(map.custom){
if(map.name.equals(toSave.name)){
out.add(toSave);
toSave.id = map.id;
added = true;
}else{
out.add(map);
}
}
}
if(!added){
out.add(toSave);
}
maps.remove(toSave.id);
mapNames.remove(toSave.name);
maps.put(toSave.id, toSave);
mapNames.put(toSave.name, toSave);
Pixmaps.write(toSave.pixmap, customMapDirectory.child(toSave.name + ".png"));
saveMaps(out, customMapDirectory.child("maps.json"));
}
private boolean loadMapFile(FileHandle file, boolean logException){
//TODO GWT support: read from prefs string if custom
public MapTileData readTileData(Map map){
try {
Array<Map> arr = json.fromJson(ArrayContainer.class, file).maps;
if (arr != null) { //can be an empty map file
for (Map map : arr) {
map.pixmap = new Pixmap(file.sibling(map.name + ".png"));
if (!headless) map.texture = new Texture(map.pixmap);
maps.put(map.id, map);
mapNames.put(map.name, map);
lastID = Math.max(lastID, map.id);
if (!map.custom) {
defaultMaps.add(map);
}
}
InputStream stream;
if (map.custom) {
stream = Gdx.files.local("maps/" + map.name + "." + mapExtension).read();
} else {
stream = customMapDirectory.child(map.name + "." + mapExtension).read();
}
return true;
}catch (GdxRuntimeException e){
Log.err(e);
return true;
}catch(Exception e){
if(logException) {
Log.err(e);
Log.err("Failed loading map file: {0}", file);
}
return false;
DataInputStream ds = new DataInputStream(stream);
MapTileData data = readTileData(ds);
ds.close();
return data;
}catch (IOException e){
throw new RuntimeException(e);
}
}
private MapTileData readTileData(DataInputStream stream) throws IOException{
MapMeta meta = readMapMeta(stream);
byte[] bytes = new byte[stream.available()];
stream.read(bytes);
return new MapTileData(bytes, meta.width, meta.height);
}
private MapMeta readMapMeta(DataInputStream stream) throws IOException{
ObjectMap<String, String> tags = new ObjectMap<>();
int version = stream.readInt();
byte tagAmount = stream.readByte();
for(int i = 0; i < tagAmount; i ++){
String name = stream.readUTF();
String value = stream.readUTF();
tags.put(name, value);
}
int width = stream.readShort();
int height = stream.readShort();
return new MapMeta(version, tags, width, height);
}
@Override
public void dispose(){
for(Map map : maps.values()){
if(map.texture != null) map.texture.dispose();
map.pixmap.dispose();
}
maps.clear();
}
public static class ArrayContainer{
Array<Map> maps;
public ArrayContainer() {
}
public ArrayContainer(Array<Map> maps) {
this.maps = maps;
}
}
private class ColorSerializer implements Serializer<Color>{
@Override
public void write(Json json, Color object, Class knownType){
json.writeValue(object.toString().substring(0, 6));
}
@Override
public Color read(Json json, JsonValue jsonData, Class type){
return Color.valueOf(jsonData.asString());
}
public void dispose() {
}
}

View File

@@ -16,9 +16,10 @@ public abstract class SaveFileVersion {
public SaveMeta getData(DataInputStream stream) throws IOException{
long time = stream.readLong(); //read last saved time
byte mode = stream.readByte(); //read the gamemode
byte map = stream.readByte(); //read the map
String map = stream.readUTF(); //read the map
int wave = stream.readInt(); //read the wave
return new SaveMeta(version, time, mode, map, wave, Difficulty.normal);
byte difficulty = stream.readByte(); //read the difficulty
return new SaveMeta(version, time, mode, map, wave, Difficulty.values()[difficulty]);
}
public abstract void read(DataInputStream stream) throws IOException;

View File

@@ -79,8 +79,8 @@ public class SaveIO{
try{
int version = stream.readInt();
SaveFileVersion ver = versions.get(version);
SaveMeta meta = ver.getData(stream);
return meta.map != null;
ver.getData(stream);
return true;
}catch (Exception e){
return false;
}

View File

@@ -2,7 +2,6 @@ package io.anuke.mindustry.io;
import io.anuke.mindustry.game.Difficulty;
import io.anuke.mindustry.game.GameMode;
import io.anuke.mindustry.world.Map;
import java.util.Date;
@@ -16,11 +15,11 @@ public class SaveMeta {
public int wave;
public Difficulty difficulty;
public SaveMeta(int version, long date, int mode, int map, int wave, Difficulty difficulty){
public SaveMeta(int version, long date, int mode, String map, int wave, Difficulty difficulty){
this.version = version;
this.date = Platform.instance.format(new Date(date));
this.mode = GameMode.values()[mode];
this.map = world.maps().getMap(map);
this.map = world.maps().getByName(map);
this.wave = wave;
this.difficulty = difficulty;
}

View File

@@ -6,7 +6,6 @@ import com.badlogic.gdx.utils.async.AsyncExecutor;
import io.anuke.mindustry.core.GameState.State;
import io.anuke.mindustry.game.Difficulty;
import io.anuke.mindustry.game.GameMode;
import io.anuke.mindustry.world.Map;
import io.anuke.ucore.core.Settings;
import io.anuke.ucore.core.Timers;

View File

@@ -8,18 +8,16 @@ import io.anuke.mindustry.game.Difficulty;
import io.anuke.mindustry.game.GameMode;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.io.SaveFileVersion;
import io.anuke.mindustry.io.SaveMeta;
import io.anuke.mindustry.resource.Item;
import io.anuke.mindustry.resource.Upgrade;
import io.anuke.mindustry.resource.Weapon;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.WorldGenerator;
import io.anuke.mindustry.world.blocks.Blocks;
import io.anuke.mindustry.world.blocks.types.BlockPart;
import io.anuke.mindustry.world.blocks.types.Rock;
import io.anuke.ucore.core.Core;
import io.anuke.ucore.entities.EntityGroup;
import io.anuke.ucore.util.Bits;
import java.io.DataInputStream;
import java.io.DataOutputStream;
@@ -34,16 +32,6 @@ public class Save16 extends SaveFileVersion {
super(16);
}
public SaveMeta getData(DataInputStream stream) throws IOException{
long time = stream.readLong(); //read last saved time
byte mode = stream.readByte(); //read the gamemode
byte map = stream.readByte(); //read the map
int wave = stream.readInt(); //read the wave
stream.readFloat(); //wave time
byte difficulty = stream.readByte();
return new SaveMeta(version, time, mode, map, wave, Difficulty.values()[difficulty]);
}
@Override
public void read(DataInputStream stream) throws IOException {
/*long loadTime = */
@@ -51,11 +39,11 @@ public class Save16 extends SaveFileVersion {
//general state
byte mode = stream.readByte();
byte mapid = stream.readByte();
String mapname = stream.readUTF();
int wave = stream.readInt();
float wavetime = stream.readFloat();
byte difficulty = stream.readByte();
float wavetime = stream.readFloat();
state.difficulty = Difficulty.values()[difficulty];
@@ -148,62 +136,44 @@ public class Save16 extends SaveFileVersion {
//map
int seed = stream.readInt();
short width = stream.readShort();
short height = stream.readShort();
world.loadMap(world.maps().getMap(mapid), seed);
if(!headless) renderer.clearTiles();
int rocks = stream.readInt();
Tile[][] tiles = world.createTiles(width, height);
for(int x = 0; x < world.width(); x ++){
for(int y = 0; y < world.height(); y ++){
Tile tile = world.tile(x, y);
for(int y = 0; y < world.height(); y ++) {
byte floorid = stream.readByte();
byte wallid = stream.readByte();
//remove breakables like rocks
if(tile.breakable()){
world.tile(x, y).setBlock(Blocks.air);
Tile tile = new Tile(x, y, floorid, wallid);
if (wallid == Blocks.blockpart.id) {
tile.link = stream.readByte();
}
if (tile.entity != null) {
byte tr = stream.readByte();
byte team = Bits.getLeftByte(tr);
byte rotation = Bits.getRightByte(tr);
short health = stream.readShort();
tile.setTeam(Team.values()[team]);
tile.entity.health = health;
tile.setRotation(rotation);
if (tile.entity.inventory != null) tile.entity.inventory.read(stream);
if (tile.entity.power != null) tile.entity.power.read(stream);
if (tile.entity.liquid != null) tile.entity.liquid.read(stream);
tile.entity.read(stream);
}
tiles[x][y] = tile;
}
}
for(int i = 0; i < rocks; i ++){
int pos = stream.readInt();
Tile tile = world.tile(pos % world.width(), pos / world.width());
if(tile == null) continue;
Block result = WorldGenerator.rocks.get(tile.floor());
if(result != null) tile.setBlock(result);
}
int tiles = stream.readInt();
for(int i = 0; i < tiles; i ++){
int pos = stream.readInt();
int blockid = stream.readInt();
Tile tile = world.tile(pos % world.width(), pos / world.width());
tile.setBlock(map.get(blockid));
if(blockid == Blocks.blockpart.id){
tile.link = stream.readByte();
}
if(tile.entity != null){
byte team = stream.readByte();
byte rotation = stream.readByte();
short health = stream.readShort();
tile.setTeam(Team.values()[team]);
tile.entity.health = health;
tile.setRotation(rotation);
if(tile.entity.inventory != null) tile.entity.inventory.read(stream);
if(tile.entity.power != null) tile.entity.power.read(stream);
if(tile.entity.liquid != null) tile.entity.liquid.read(stream);
tile.entity.read(stream);
}
}
if(!headless) renderer.clearTiles();
}
@Override
@@ -214,11 +184,11 @@ public class Save16 extends SaveFileVersion {
//--GENERAL STATE--
stream.writeByte(state.mode.ordinal()); //gamemode
stream.writeByte(world.getMap().id); //map ID
stream.writeUTF(world.getMap().name); //map ID
stream.writeInt(state.wave); //wave
stream.writeByte(state.difficulty.ordinal()); //difficulty ordinal
stream.writeFloat(state.wavetime); //wave countdown
stream.writeByte(state.difficulty.ordinal());
//--BLOCK HEADER--
@@ -286,65 +256,31 @@ public class Save16 extends SaveFileVersion {
//--MAP DATA--
//seed
stream.writeInt(world.getSeed());
int totalblocks = 0;
int totalrocks = 0;
//write world size
stream.writeShort(world.width());
stream.writeShort(world.height());
//now write all blocks
for(int x = 0; x < world.width(); x ++){
for(int y = 0; y < world.height(); y ++){
Tile tile = world.tile(x, y);
if(tile != null && tile.breakable()){
if(tile.block() instanceof Rock){
totalrocks ++;
}else{
totalblocks ++;
}
stream.writeByte(tile.floor().id); //floor ID
stream.writeByte(tile.block().id); //wall ID
if(tile.block() instanceof BlockPart){
stream.writeByte(tile.link);
}
}
}
//amount of rocks
stream.writeInt(totalrocks);
if(tile.entity != null){
stream.writeByte(Bits.packByte((byte)tile.getTeam().ordinal(), tile.getRotation())); //team + rotation
stream.writeShort((short)tile.entity.health); //health
//write all rocks
for(int x = 0; x < world.width(); x ++) {
for (int y = 0; y < world.height(); y++) {
Tile tile = world.tile(x, y);
if(tile.entity.inventory != null) tile.entity.inventory.write(stream);
if(tile.entity.power != null) tile.entity.power.write(stream);
if(tile.entity.liquid != null) tile.entity.liquid.write(stream);
if (tile != null && tile.block() instanceof Rock) {
stream.writeInt(tile.packedPosition());
}
}
}
//write all blocks
stream.writeInt(totalblocks);
for(int x = 0; x < world.width(); x ++){
for(int y = 0; y < world.height(); y ++){
Tile tile = world.tile(x, y);
if(tile != null && tile.breakable() && !(tile.block() instanceof Rock)){
stream.writeInt(x + y*world.width()); //tile pos
stream.writeInt(tile.block().id); //block ID
if(tile.block() instanceof BlockPart) stream.writeByte(tile.link);
if(tile.entity != null){
stream.writeByte(tile.getTeam().ordinal());
stream.writeByte(tile.getRotation()); //rotation
stream.writeShort((short)tile.entity.health); //health
if(tile.entity.inventory != null) tile.entity.inventory.write(stream);
if(tile.entity.power != null) tile.entity.power.write(stream);
if(tile.entity.liquid != null) tile.entity.liquid.write(stream);
tile.entity.write(stream);
}
tile.entity.write(stream);
}
}
}

View File

@@ -1,40 +0,0 @@
package io.anuke.mindustry.mapeditor;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.utils.Disposable;
import io.anuke.ucore.graphics.Pixmaps;
public class DrawOperation implements Disposable{
Pixmap from, to, pixmap;
public DrawOperation(Pixmap pixmap){
this.pixmap = pixmap;
}
public void add(Pixmap from, Pixmap to) {
this.from = from;
this.to = to;
}
public void undo() {
if(from != null) pixmap.drawPixmap(from, 0, 0);
}
public void redo() {
if(to != null) pixmap.drawPixmap(to, 0, 0);
}
@Override
public void dispose() {
if(!Pixmaps.isDisposed(from))
from.dispose();
if(!Pixmaps.isDisposed(to))
to.dispose();
}
public void disposeFrom(){
if(from != null) from.dispose();
}
}

View File

@@ -1,87 +0,0 @@
package io.anuke.mindustry.mapeditor;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.math.GridPoint2;
import com.badlogic.gdx.utils.IntSet;
import static io.anuke.mindustry.Vars.*;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.ColorMapper;
import io.anuke.mindustry.world.ColorMapper.BlockPair;
import java.util.Stack;
public enum EditorTool{
pick{
public void touched(MapEditor editor, int x, int y){
BlockPair pair = ColorMapper.get(editor.pixmap().getPixel(x, y));
if(pair == null) return;
Block block = pair.dominant();
editor.setDrawBlock(block);
ui.editor.updateSelectedBlock();
}
},
pencil{
{
edit = true;
}
public void touched(MapEditor editor, int x, int y){
editor.draw(x, y);
}
},
line{
{
}
},
fill{
{
edit = true;
}
public void touched(MapEditor editor, int x, int y){
Pixmap pix = editor.pixmap();
int dest = pix.getPixel(x, y);
int width = pix.getWidth();
IntSet set = new IntSet();
Stack<GridPoint2> points = new Stack<GridPoint2>();
points.add(new GridPoint2(x, y));
while( !points.isEmpty()){
GridPoint2 pos = points.pop();
set.add(asInt(pos.x, pos.y, width));
int pcolor = pix.getPixel(pos.x, pos.y);
if(colorEquals(pcolor, dest)){
pix.drawPixel(pos.x, pos.y);
if(pos.x > 0 && !set.contains(asInt(pos.x - 1, pos.y, width))) points.add(new GridPoint2(pos).cpy().add( -1, 0));
if(pos.y > 0 && !set.contains(asInt(pos.x, pos.y - 1, width))) points.add(new GridPoint2(pos).cpy().add(0, -1));
if(pos.x < pix.getWidth() - 1 && !set.contains(asInt(pos.x + 1, pos.y, width))) points.add(new GridPoint2(pos).cpy().add(1, 0));
if(pos.y < pix.getHeight() - 1 && !set.contains(asInt(pos.x, pos.y + 1, width))) points.add(new GridPoint2(pos).cpy().add(0, 1));
}
}
editor.updateTexture();
}
int asInt(int x, int y, int width){
return x+y*width;
}
boolean colorEquals(int a, int b){
return a == b;
}
},
zoom;
boolean edit;
public void touched(MapEditor editor, int x, int y){
}
}

View File

@@ -1,201 +0,0 @@
package io.anuke.mindustry.mapeditor;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.graphics.Texture;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.ColorMapper;
import io.anuke.mindustry.world.Map;
import io.anuke.mindustry.world.blocks.Blocks;
import io.anuke.ucore.graphics.Pixmaps;
public class MapEditor{
public static final int[] validMapSizes = {128, 256, 512};
public static final int[] brushSizes = {1, 2, 3, 4, 5, 9, 15};
public static final int maxSpawnpoints = 15;
public static final Format format = Format.RGBA8888;
private Pixmap[] brushPixmaps = new Pixmap[brushSizes.length];
private Map map;
private MapFilter filter = new MapFilter();
private Pixmap filterPixmap;
private Texture filterTexture;
private Pixmap pixmap;
private Texture texture;
private int brushSize = 1;
private Block drawBlock = Blocks.stone;
public MapEditor(){
for(int i = 0; i < brushSizes.length; i ++){
int s = brushSizes[i];
brushPixmaps[i] = new Pixmap(s*2-1, s*2-1, format);
}
}
public Map getMap(){
return map;
}
public void updateTexture(){
texture.draw(pixmap, 0, 0);
}
public MapFilter getFilter(){
return filter;
}
public void applyFilterPreview(){
if(filterPixmap != null && (filterPixmap.getWidth() != pixmap.getWidth()
|| filterPixmap.getHeight() != pixmap.getHeight())){
filterPixmap.dispose();
filterTexture.dispose();
filterPixmap = null;
filterTexture = null;
}
if(filterPixmap == null){
filterPixmap = Pixmaps.copy(pixmap);
filter.process(filterPixmap);
filterTexture = new Texture(filterPixmap);
}else{
filterPixmap.drawPixmap(pixmap, 0, 0);
filter.process(filterPixmap);
filterTexture.draw(filterPixmap, 0, 0);
}
}
public Texture getFilterTexture(){
return filterTexture;
}
public void applyFilter(){
filter.process(pixmap);
texture.draw(pixmap, 0, 0);
}
public void beginEdit(Map map){
drawBlock = Blocks.stone;
this.map = map;
this.brushSize = 1;
if(map.pixmap == null){
pixmap = new Pixmap(256, 256, format);
pixmap.setColor(ColorMapper.getColor(drawBlock));
pixmap.fill();
texture = new Texture(pixmap);
}else{
pixmap = map.pixmap;
texture = map.texture;
pixmap.setColor(ColorMapper.getColor(drawBlock));
}
}
public Block getDrawBlock(){
return drawBlock;
}
public void setDrawBlock(Block block){
this.drawBlock = block;
pixmap.setColor(ColorMapper.getColor(block));
}
public void setBrushSize(int size){
this.brushSize = size;
}
public int getBrushSize() {
return brushSize;
}
public void draw(int dx, int dy){
if(dx < 0 || dy < 0 || dx >= pixmap.getWidth() || dy >= pixmap.getHeight()){
return;
}
Gdx.gl.glBindTexture(GL20.GL_TEXTURE_2D, texture.getTextureObjectHandle());
int dstWidth = brushSize*2-1;
int dstHeight = brushSize*2-1;
int width = pixmap.getWidth(), height = pixmap.getHeight();
int x = dx - dstWidth/2;
int y = dy - dstHeight/2;
if (x + dstWidth > width){
x = width - dstWidth;
}else if (x < 0){
x = 0;
}
if (y + dstHeight > height){
dstHeight = height - y;
}else if (y < 0){
dstHeight += y;
y = 0;
}
pixmap.fillCircle(dx, dy, brushSize-1);
Pixmap dst = brush(brushSize);
dst.drawPixmap(pixmap, x, y, dstWidth, dstHeight, 0, 0, dstWidth, dstHeight);
Gdx.gl.glTexSubImage2D(GL20.GL_TEXTURE_2D, 0, x, y, dstWidth, dstHeight,
dst.getGLFormat(), dst.getGLType(), dst.getPixels());
}
private Pixmap brush(int size){
for(int i = 0; i < brushSizes.length; i ++){
if(brushSizes[i] == size){
return brushPixmaps[i];
}
}
return null;
}
public Texture texture(){
return texture;
}
public Pixmap pixmap(){
return pixmap;
}
public void setPixmap(Pixmap out){
if(pixmap.getWidth() == out.getWidth() && pixmap.getHeight() == out.getHeight()){
pixmap.dispose();
pixmap = out;
texture.draw(out, 0, 0);
}else{
pixmap.dispose();
texture.dispose();
pixmap = out;
texture = new Texture(out);
}
pixmap.setColor(ColorMapper.getColor(drawBlock));
map.pixmap = pixmap;
map.texture = texture;
}
public void resize(int width, int height){
Pixmap out = Pixmaps.resize(pixmap, width, height, ColorMapper.getColor(Blocks.stone));
pixmap.dispose();
pixmap = out;
texture.dispose();
texture = new Texture(out);
if(filterPixmap != null){
filterPixmap.dispose();
filterTexture.dispose();
filterPixmap = null;
filterTexture = null;
}
pixmap.setColor(ColorMapper.getColor(drawBlock));
}
}

View File

@@ -1,439 +0,0 @@
package io.anuke.mindustry.mapeditor;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Texture;
import io.anuke.mindustry.io.Platform;
import io.anuke.mindustry.ui.dialogs.FileChooser;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.ColorMapper;
import io.anuke.mindustry.world.ColorMapper.BlockPair;
import io.anuke.mindustry.world.Map;
import io.anuke.mindustry.world.blocks.Blocks;
import io.anuke.mindustry.world.blocks.SpecialBlocks;
import io.anuke.ucore.core.Core;
import io.anuke.ucore.core.Graphics;
import io.anuke.ucore.core.Inputs;
import io.anuke.ucore.core.Timers;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.graphics.Pixmaps;
import io.anuke.ucore.scene.Element;
import io.anuke.ucore.scene.builders.build;
import io.anuke.ucore.scene.builders.imagebutton;
import io.anuke.ucore.scene.builders.label;
import io.anuke.ucore.scene.builders.table;
import io.anuke.ucore.scene.ui.*;
import io.anuke.ucore.scene.ui.layout.Table;
import io.anuke.ucore.util.Bundles;
import io.anuke.ucore.util.Log;
import io.anuke.ucore.util.Strings;
import java.util.Arrays;
import static io.anuke.mindustry.Vars.*;
public class MapEditorDialog extends Dialog{
private MapEditor editor;
private MapView view;
private MapGenerateDialog dialog;
private MapLoadDialog loadDialog;
private MapSaveDialog saveDialog;
private MapResizeDialog resizeDialog;
private ScrollPane pane;
private FileChooser openFile, saveFile;
private boolean saved = false;
private ButtonGroup<ImageButton> blockgroup;
public MapEditorDialog(){
super("$text.mapeditor", "dialog");
if(gwt) return;
editor = new MapEditor();
dialog = new MapGenerateDialog(editor);
view = new MapView(editor);
openFile = new FileChooser("$text.loadimage", FileChooser.pngFilter, true, file -> {
ui.loadfrag.show();
Timers.run(3f, () -> {
try{
Pixmap pixmap = new Pixmap(file);
if(verifySize(pixmap)){
editor.setPixmap(pixmap);
view.clearStack();
}else{
ui.showError(Bundles.format("text.editor.badsize", Arrays.toString(MapEditor.validMapSizes)));
}
}catch (Exception e){
ui.showError(Bundles.format("text.editor.errorimageload", Strings.parseException(e, false)));
Log.err(e);
}
ui.loadfrag.hide();
});
});
saveFile = new FileChooser("$saveimage", false, file -> {
if(!file.extension().toLowerCase().equals(".png")){
file = file.parent().child(file.nameWithoutExtension() + ".png");
}
FileHandle result = file;
ui.loadfrag.show();
Timers.run(3f, () -> {
try{
Pixmaps.write(editor.pixmap(), result);
}catch (Exception e){
ui.showError(Bundles.format("text.editor.errorimagesave", Strings.parseException(e, false)));
if(!android) Log.err(e);
}
ui.loadfrag.hide();
});
});
loadDialog = new MapLoadDialog(map -> {
saveDialog.setFieldText(map.name);
ui.loadfrag.show();
Timers.run(3f, () -> {
Map copy = new Map();
copy.name = map.name;
copy.id = -1;
copy.pixmap = Pixmaps.copy(map.pixmap);
copy.texture = new Texture(copy.pixmap);
copy.oreGen = map.oreGen;
editor.beginEdit(copy);
ui.loadfrag.hide();
view.clearStack();
});
});
resizeDialog = new MapResizeDialog(editor, (x, y) -> {
Pixmap pix = editor.pixmap();
if(!(pix.getWidth() == x && pix.getHeight() == y)){
ui.loadfrag.show();
Timers.run(10f, ()->{
editor.resize(x, y);
view.clearStack();
ui.loadfrag.hide();
});
}
});
saveDialog = new MapSaveDialog(name -> {
ui.loadfrag.show();
if(verifyMap()){
saved = true;
String before = editor.getMap().name;
editor.getMap().name = name;
Timers.run(10f, () -> {
world.maps().saveAndReload(editor.getMap(), editor.pixmap());
loadDialog.rebuild();
ui.loadfrag.hide();
view.clearStack();
if(!name.equals(before)) {
Map map = new Map();
map.name = editor.getMap().name;
map.oreGen = editor.getMap().oreGen;
map.pixmap = Pixmaps.copy(editor.getMap().pixmap);
map.texture = new Texture(map.pixmap);
map.custom = true;
editor.beginEdit(map);
}
});
}else{
ui.loadfrag.hide();
}
});
setFillParent(true);
clearChildren();
margin(0);
build.begin(this);
build();
build.end();
tapped(() -> {
Element e = Core.scene.hit(Graphics.mouse().x, Graphics.mouse().y, true);
if(e == null || !e.isDescendantOf(pane)) Core.scene.setScrollFocus(null);
});
update(() -> {
if(Core.scene != null && Core.scene.getKeyboardFocus() == this){
doInput();
}
});
shown(() -> {
saved = true;
editor.beginEdit(new Map());
blockgroup.getButtons().get(2).setChecked(true);
Core.scene.setScrollFocus(view);
view.clearStack();
Timers.runTask(10f, Platform.instance::updateRPC);
});
hidden(() -> Platform.instance.updateRPC());
}
public MapView getView() {
return view;
}
public void resetSaved(){
saved = false;
}
public void updateSelectedBlock(){
Block block = editor.getDrawBlock();
int i = 0;
for(BlockPair pair : ColorMapper.getPairs()){
if(pair.wall == block || (pair.wall == Blocks.air && pair.floor == block)){
blockgroup.getButtons().get(i).setChecked(true);
break;
}
i++;
}
}
public boolean hasPane(){
return Core.scene.getScrollFocus() == pane;
}
public void build(){
new table(){{
float isize = 16*2f;
aleft();
new table(){{
defaults().growY().width(130f).padBottom(-6);
new imagebutton("icon-terrain", isize, () ->
dialog.show()
).text("$text.editor.generate");
row();
new imagebutton("icon-resize", isize, () ->
resizeDialog.show()
).text("$text.editor.resize").padTop(4f);
row();
new imagebutton("icon-load-map", isize, () ->
loadDialog.show()
).text("$text.editor.loadmap");
row();
new imagebutton("icon-save-map", isize, ()->
saveDialog.show()
).text("$text.editor.savemap");
row();
new imagebutton("icon-load-image", isize, () ->
openFile.show()
).text("$text.editor.loadimage");
row();
new imagebutton("icon-save-image", isize, () ->
saveFile.show()
).text("$text.editor.saveimage");
row();
new imagebutton("icon-back", isize, () -> {
if(!saved){
ui.showConfirm("$text.confirm", "$text.editor.unsaved",
MapEditorDialog.this::hide);
}else{
hide();
}
}).padBottom(0).text("$text.back");
}}.left().growY().end();
new table("button"){{
add(view).grow();
}}.grow().end();
new table(){{
Table tools = new Table("button");
tools.top();
tools.marginTop(0).marginBottom(6);
ButtonGroup<ImageButton> group = new ButtonGroup<>();
int i = 1;
tools.defaults().size(53f, 58f).padBottom(-6);
ImageButton undo = tools.addImageButton("icon-undo", 16*2f, () -> view.undo()).get();
ImageButton redo = tools.addImageButton("icon-redo", 16*2f, () -> view.redo()).get();
ImageButton grid = tools.addImageButton("icon-grid", "toggle", 16*2f, () -> view.setGrid(!view.isGrid())).get();
undo.setDisabled(() -> !view.getStack().canUndo());
redo.setDisabled(() -> !view.getStack().canRedo());
undo.update(() -> undo.getImage().setColor(undo.isDisabled() ? Color.GRAY : Color.WHITE));
redo.update(() -> redo.getImage().setColor(redo.isDisabled() ? Color.GRAY : Color.WHITE));
grid.update(() -> grid.setChecked(view.isGrid()));
for(EditorTool tool : EditorTool.values()){
ImageButton button = new ImageButton("icon-" + tool.name(), "toggle");
button.clicked(() -> view.setTool(tool));
button.resizeImage(16*2f);
button.update(() -> button.setChecked(view.getTool() == tool));
group.add(button);
if (tool == EditorTool.pencil)
button.setChecked(true);
tools.add(button).padBottom(-6f);
if(i++ % 4 == 1) tools.row();
}
add(tools).width(53*4).padBottom(-6);
row();
new table("button"){{
margin(10f);
Slider slider = new Slider(0, MapEditor.brushSizes.length-1, 1, false);
slider.moved(f -> editor.setBrushSize(MapEditor.brushSizes[(int)(float)f]));
new label(() -> Bundles.format("text.editor.brushsize", MapEditor.brushSizes[(int)slider.getValue()])).left();
row();
add(slider).growX().padTop(4f);
}}.growX().padBottom(-6).end();
row();
new table("button"){{
get().addCheck("$text.oregen", b -> editor.getMap().oreGen = b)
.update(c -> c.setChecked(editor.getMap().oreGen)).padTop(3).padBottom(3);
}}.growX().padBottom(-6).end();
row();
addBlockSelection(get());
row();
}}.right().growY().end();
}}.grow().end();
}
private void doInput(){
//tool select
for(int i = 0; i < EditorTool.values().length; i ++){
int code = i == 0 ? 5 : i;
if(Inputs.keyTap("weapon_" + code)){
view.setTool(EditorTool.values()[i]);
break;
}
}
//ctrl keys (undo, redo, save)
if(Inputs.keyDown(Keys.CONTROL_LEFT)){
if(Inputs.keyTap(Keys.Z)){
view.undo();
}
if(Inputs.keyTap(Keys.Y)){
view.redo();
}
if(Inputs.keyTap(Keys.S)){
saveDialog.save();
}
if(Inputs.keyTap(Keys.G)){
view.setGrid(!view.isGrid());
}
}
}
private boolean verifySize(Pixmap pix){
boolean w = false, h = false;
for(int i : MapEditor.validMapSizes){
if(pix.getWidth() == i)
w = true;
if(pix.getHeight() == i)
h = true;
}
return w && h;
}
private boolean verifyMap(){
int psc = ColorMapper.getColor(SpecialBlocks.playerSpawn);
int esc = ColorMapper.getColor(SpecialBlocks.enemySpawn);
int playerSpawns = 0;
int enemySpawns = 0;
Pixmap pix = editor.pixmap();
for(int x = 0; x < pix.getWidth(); x ++){
for(int y = 0; y < pix.getHeight(); y ++){
int i = pix.getPixel(x, y);
if(i == psc) playerSpawns ++;
if(i == esc) enemySpawns ++;
}
}
if(playerSpawns == 0){
ui.showError("$text.editor.noplayerspawn");
return false;
}else if(playerSpawns > 1){
ui.showError("$text.editor.manyplayerspawns");
return false;
}
if(enemySpawns > MapEditor.maxSpawnpoints){
ui.showError(Bundles.format("text.editor.manyenemyspawns", MapEditor.maxSpawnpoints));
return false;
}
return true;
}
private void addBlockSelection(Table table){
Table content = new Table();
pane = new ScrollPane(content, "volume");
pane.setScrollingDisabled(true, false);
pane.setFadeScrollBars(false);
pane.setOverscroll(true, false);
ButtonGroup<ImageButton> group = new ButtonGroup<>();
blockgroup = group;
int i = 0;
for(BlockPair pair : ColorMapper.getPairs()){
Block block = pair.wall == Blocks.air ? pair.floor : pair.wall;
ImageButton button = new ImageButton(Draw.hasRegion(block.name) ? Draw.region(block.name) : Draw.region(block.name + "1"), "toggle");
button.clicked(() -> editor.setDrawBlock(block));
button.resizeImage(8*4f);
group.add(button);
content.add(button).pad(4f).size(53f, 58f);
if(i++ % 2 == 1){
content.row();
}
}
group.getButtons().get(2).setChecked(true);
Table extra = new Table("button");
extra.labelWrap(() -> editor.getDrawBlock().formalName).width(180f).center();
table.add(extra).padBottom(-6).growX();
table.row();
table.add(pane).growY().fillX();
}
}

View File

@@ -1,244 +0,0 @@
package io.anuke.mindustry.mapeditor;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.ObjectMap;
import com.badlogic.gdx.utils.OrderedMap;
import io.anuke.mindustry.world.Block;
import io.anuke.mindustry.world.ColorMapper;
import io.anuke.mindustry.world.ColorMapper.BlockPair;
import io.anuke.mindustry.world.blocks.Blocks;
import io.anuke.mindustry.world.blocks.types.Floor;
import io.anuke.ucore.graphics.Pixmaps;
import io.anuke.ucore.noise.RidgedPerlin;
import io.anuke.ucore.noise.Simplex;
import io.anuke.ucore.util.Mathf;
public class MapFilter{
private ObjectMap<String, GenPref> prefs = map(
pref("replace", "whether to replace blocks"),
pref("terrain", "generate new terrain"),
pref("circle", "generate terrain in a circle"),
pref("distort", "distort the map image"),
pref("sand", "add patches of sand"),
pref("grass", "add patches of grass"),
pref("stone", "add patches of stone"),
pref("blackstone", "add patches of black stone"),
pref("allgrass", "fill map with grass"),
pref("allsnow", "fill map with snow"),
pref("allsand", "fill map with sand"),
pref("water", "add lakes"),
pref("oil", "add oil lakes"),
pref("lavariver", "add lava rivers"),
pref("slavariver", "ad small lava rivers"),
pref("river", "add rivers"),
pref("iceriver", "add frozen rivers"),
pref("oilriver", "add oil rivers")
);
private Simplex sim = new Simplex();
private RidgedPerlin rid = new RidgedPerlin(1, 10, 20f);
private RidgedPerlin rid2 = new RidgedPerlin(1, 6, 1f);
private RidgedPerlin rid3 = new RidgedPerlin(1, 6, 1f);
public MapFilter(){
prefs.get("replace").enabled = true;
prefs.get("terrain").enabled = true;
randomize();
}
public void randomize(){
sim.setSeed(Mathf.random(999999));
rid.setSeed(Mathf.random(999999));
rid2.setSeed(Mathf.random(999999));
rid3.setSeed(Mathf.random(999999));
}
public ObjectMap<String, GenPref> getPrefs(){
return prefs;
}
public Pixmap process(Pixmap pixmap){
if(prefs.get("terrain").enabled){
for(int x = 0; x < pixmap.getWidth(); x++){
for(int y = 0; y < pixmap.getHeight(); y++){
float dist = Vector2.dst((float) x / pixmap.getWidth(), (float) y / pixmap.getHeight(), 0.5f, 0.5f) * 2f;
double noise = sim.octaveNoise2D(6, 0.6, 1 / 180.0, x, y + 9999) / (prefs.get("circle").enabled ? 1.7 : 1f) + dist / 10f;
if(dist > 0.8){
noise += 2 * (dist - 0.8);
}
Block block = noise > 0.6 ? Blocks.stoneblock : Blocks.stone;
pixmap.drawPixel(x, y, ColorMapper.getColor(block));
}
}
}
Pixmap src = Pixmaps.copy(pixmap);
for(int x = 0; x < pixmap.getWidth(); x++){
for(int y = 0; y < pixmap.getHeight(); y++){
int dx = 0, dy = 0;
if(prefs.get("distort").enabled){
double intensity = 12;
double scale = 80;
double octaves = 4;
double falloff = 0.6;
double nx = (sim.octaveNoise2D(octaves, falloff, 1 / scale, x, y) - 0.5f) * intensity;
double ny = (sim.octaveNoise2D(octaves, falloff, 1 / scale, x, y + 99999) - 0.5f) * intensity;
dx = (int) nx;
dy = (int) ny;
}
int pix = src.getPixel(x + dx, y + dy);
BlockPair pair = ColorMapper.get(pix);
Block block = pair == null ? null : pair.wall == Blocks.air ? pair.floor : pair.wall;
if(block == null)
continue;
boolean floor = block instanceof Floor;
double noise = sim.octaveNoise2D(4, 0.6, 1 / 170.0, x, y) + sim.octaveNoise2D(1, 1.0, 1 / 5.0, x, y) / 18.0;
double nwater = sim.octaveNoise2D(1, 1.0, 1 / 130.0, x, y);
noise += nwater / 5.0;
double noil = sim.octaveNoise2D(1, 1.0, 1 / 150.0, x + 9999, y) + sim.octaveNoise2D(1, 1.0, 1 / 2.0, x, y) / 290.0;
if(!floor || prefs.get("replace").enabled){
if(prefs.get("allgrass").enabled){
block = floor ? Blocks.grass : Blocks.grassblock;
}else if(prefs.get("allsnow").enabled){
block = floor ? Blocks.snow : Blocks.snowblock;
}else if(prefs.get("allsand").enabled){
block = floor ? Blocks.sand : Blocks.sandblock;
}else if(prefs.get("replace").enabled){
block = floor ? Blocks.stone : Blocks.stoneblock;
}
if(noise > 0.7 && prefs.get("grass").enabled){
block = floor ? Blocks.grass : Blocks.grassblock;
}
if(noise > 0.7 && prefs.get("blackstone").enabled){
block = floor ? Blocks.blackstone : Blocks.blackstoneblock;
}
if(noise > 0.7 && prefs.get("sand").enabled){
block = floor ? Blocks.sand : Blocks.sandblock;
}
if(noise > 0.8 && prefs.get("stone").enabled){
block = floor ? Blocks.stone : Blocks.stoneblock;
}
}
if(floor){
if(nwater > 0.93 && prefs.get("water").enabled){
block = Blocks.water;
if(nwater > 0.943){
block = Blocks.deepwater;
}
}
if(noil > 0.95 && prefs.get("oil").enabled){
block = Blocks.dirt;
if(noil > 0.955){
block = Blocks.oil;
}
}
}
if(floor && prefs.get("lavariver").enabled){
double lava = rid.getValue(x, y, 1 / 100f);
double t = 0.6;
if(lava > t){
block = Blocks.lava;
}else if(lava > t - 0.2){
block = Blocks.blackstone;
}
}
if(floor && prefs.get("slavariver").enabled){
double lava = rid.getValue(x, y, 1 / 40f);
double t = 0.7;
if(lava > t){
block = Blocks.lava;
}else if(lava > t - 0.3){
block = Blocks.blackstone;
}
}
if(floor && prefs.get("oilriver").enabled){
double lava = rid3.getValue(x, y, 1 / 100f);
double t = 0.9;
if(lava > t){
block = Blocks.oil;
}else if(lava > t - 0.2){
block = Blocks.dirt;
}
}
if(floor && prefs.get("river").enabled){
double riv = rid2.getValue(x, y, 1 / 140f);
double t = 0.4;
if(riv > t + 0.1){
block = Blocks.deepwater;
}else if(riv > t){
block = Blocks.water;
}else if(riv > t - 0.2){
block = Blocks.grass;
}
}
if(floor && prefs.get("iceriver").enabled){
double riv = rid2.getValue(x, y, 1 / 140f);
double t = 0.4;
if(riv > t + 0.1){
block = Blocks.ice;
}else if(riv > t){
block = Blocks.ice;
}else if(riv > t - 0.2){
block = Blocks.snow;
}
}
pixmap.drawPixel(x, y, ColorMapper.getColor(block));
}
}
src.dispose();
return pixmap;
}
private static OrderedMap<String, GenPref> map(GenPref...objects){
OrderedMap<String, GenPref> prefs = new OrderedMap<>();
for(int i = 0; i < objects.length; i ++){
GenPref pref = (GenPref)objects[i];
prefs.put(pref.name, pref);
}
return prefs;
}
private GenPref pref(String name, String desc){
return new GenPref(name, desc);
}
class GenPref{
public final String name;
public final String description;
public boolean enabled;
GenPref(String name, String description){
this.name = name;
this.description = description;
}
}
}

View File

@@ -1,105 +0,0 @@
package io.anuke.mindustry.mapeditor;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.utils.Align;
import com.badlogic.gdx.utils.Scaling;
import static io.anuke.mindustry.Vars.*;
import io.anuke.mindustry.mapeditor.MapFilter.GenPref;
import io.anuke.mindustry.ui.BorderImage;
import io.anuke.mindustry.ui.dialogs.FloatingDialog;
import io.anuke.ucore.core.Timers;
import io.anuke.ucore.graphics.Pixmaps;
import io.anuke.ucore.scene.style.TextureRegionDrawable;
import io.anuke.ucore.scene.ui.CheckBox;
import io.anuke.ucore.scene.ui.Image;
import io.anuke.ucore.scene.ui.ScrollPane;
import io.anuke.ucore.scene.ui.layout.Stack;
import io.anuke.ucore.scene.ui.layout.Table;
public class MapGenerateDialog extends FloatingDialog{
private MapEditor editor;
private Image image;
private boolean loading;
public MapGenerateDialog(MapEditor editor) {
super("$text.editor.generate");
this.editor = editor;
Stack stack = new Stack();
stack.add(image = new BorderImage());
Image loadImage = new Image("icon-loading");
loadImage.setScaling(Scaling.none);
loadImage.setScale(3f);
loadImage.update(() -> loadImage.setOrigin(Align.center));
loadImage.setVisible(() -> loading);
Image next = new Image("white");
next.setScaling(Scaling.fit);
next.setColor(0, 0, 0, 0.6f);
next.setVisible(() -> loading);
stack.add(next);
stack.add(loadImage);
content().add(stack).grow();
image.setScaling(Scaling.fit);
Table preft = new Table();
preft.left();
preft.margin(4f).marginRight(25f);
for(GenPref pref : editor.getFilter().getPrefs().values()){
CheckBox box = new CheckBox(pref.name);
box.setChecked(pref.enabled);
box.changed(() -> pref.enabled = box.isChecked());
preft.add(box).pad(4f).left();
preft.row();
}
ScrollPane pane = new ScrollPane(preft, "volume");
pane.setFadeScrollBars(false);
pane.setScrollingDisabled(true, false);
content().add(pane).fillY();
buttons().defaults().size(170f, 50f).pad(4f);
buttons().addButton("$text.back", this::hide);
buttons().addButton("$text.randomize", () ->{
editor.getFilter().randomize();
apply();
});
buttons().addButton("$text.update", this::apply);
buttons().addButton("$text.apply", () ->{
ui.loadfrag.show();
Timers.run(3f, () ->{
Pixmap copy = Pixmaps.copy(editor.pixmap());
editor.applyFilter();
ui.editor.getView().push(copy, Pixmaps.copy(editor.pixmap()));
ui.loadfrag.hide();
ui.editor.resetSaved();
hide();
});
});
shown(() ->{
loading = true;
Timers.run(30f, () -> {
editor.applyFilterPreview();
image.setDrawable(new TextureRegionDrawable(new TextureRegion(editor.getFilterTexture())));
loading = false;
});
});
}
private void apply(){
loading = true;
Timers.run(3f, () -> {
editor.applyFilterPreview();
loading = false;
});
}
}

View File

@@ -1,73 +0,0 @@
package io.anuke.mindustry.mapeditor;
import io.anuke.mindustry.ui.BorderImage;
import io.anuke.mindustry.ui.dialogs.FloatingDialog;
import io.anuke.mindustry.world.Map;
import io.anuke.ucore.function.Consumer;
import io.anuke.ucore.scene.ui.ButtonGroup;
import io.anuke.ucore.scene.ui.ScrollPane;
import io.anuke.ucore.scene.ui.TextButton;
import io.anuke.ucore.scene.ui.layout.Table;
import static io.anuke.mindustry.Vars.world;
public class MapLoadDialog extends FloatingDialog{
private Map selected = world.maps().getMap(0);
public MapLoadDialog(Consumer<Map> loader) {
super("$text.editor.loadmap");
shown(this::rebuild);
rebuild();
TextButton button = new TextButton("$text.load");
button.setDisabled(() -> selected == null);
button.clicked(() -> {
if (selected != null) {
loader.accept(selected);
hide();
}
});
buttons().defaults().size(200f, 50f);
buttons().addButton("$text.cancel", this::hide);
buttons().add(button);
}
public void rebuild(){
content().clear();
selected = world.maps().getMap(0);
ButtonGroup<TextButton> group = new ButtonGroup<>();
int maxcol = 3;
int i = 0;
Table table = new Table();
table.defaults().size(200f, 90f).pad(4f);
table.margin(10f);
ScrollPane pane = new ScrollPane(table, "horizontal");
pane.setFadeScrollBars(false);
for (Map map : world.maps().list()) {
if (!map.visible) continue;
TextButton button = new TextButton(map.localized(), "toggle");
button.add(new BorderImage(map.texture, 2f)).size(16 * 4f);
button.getCells().reverse();
button.clicked(() -> selected = map);
button.getLabelCell().grow().left().padLeft(5f);
group.add(button);
table.add(button);
if (++i % maxcol == 0) table.row();
}
content().add("$text.editor.loadmap");
content().row();
content().add(pane);
}
}

View File

@@ -1,67 +0,0 @@
package io.anuke.mindustry.mapeditor;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.utils.Align;
import io.anuke.mindustry.ui.dialogs.FloatingDialog;
import io.anuke.ucore.function.BiConsumer;
import io.anuke.ucore.scene.ui.ButtonGroup;
import io.anuke.ucore.scene.ui.TextButton;
import io.anuke.ucore.scene.ui.layout.Table;
public class MapResizeDialog extends FloatingDialog{
int width, height;
public MapResizeDialog(MapEditor editor, BiConsumer<Integer, Integer> cons){
super("$text.editor.resizemap");
shown(() -> {
content().clear();
Pixmap pix = editor.pixmap();
width = pix.getWidth();
height = pix.getHeight();
Table table = new Table();
for(int d = 0; d < 2; d ++){
boolean w = d == 0;
int curr = d == 0 ? pix.getWidth() : pix.getHeight();
int idx = 0;
for(int i = 0; i < MapEditor.validMapSizes.length; i ++)
if(MapEditor.validMapSizes[i] == curr) idx = i;
table.add(d == 0 ? "$text.width": "$text.height").padRight(8f);
ButtonGroup<TextButton> group = new ButtonGroup<>();
for(int i = 0; i < MapEditor.validMapSizes.length; i ++){
int size = MapEditor.validMapSizes[i];
TextButton button = new TextButton(size + "", "toggle");
button.clicked(() -> {
if(w)
width = size;
else
height = size;
});
group.add(button);
if(i == idx) button.setChecked(true);
table.add(button).size(100f, 54f).pad(2f);
}
table.row();
}
content().label(() ->
width + height > 512 ? "$text.editor.resizebig" : ""
).get().setAlignment(Align.center, Align.center);
content().row();
content().add(table);
});
buttons().defaults().size(200f, 50f);
buttons().addButton("$text.cancel", this::hide);
buttons().addButton("$text.editor.resize", () -> {
cons.accept(width, height);
hide();
});
}
}

View File

@@ -1,74 +0,0 @@
package io.anuke.mindustry.mapeditor;
import io.anuke.mindustry.io.Platform;
import io.anuke.mindustry.ui.dialogs.FloatingDialog;
import io.anuke.mindustry.world.Map;
import io.anuke.ucore.function.Consumer;
import io.anuke.ucore.scene.ui.TextButton;
import io.anuke.ucore.scene.ui.TextField;
import static io.anuke.mindustry.Vars.*;
public class MapSaveDialog extends FloatingDialog{
private TextField field;
private Consumer<String> listener;
public MapSaveDialog(Consumer<String> cons){
super("$text.editor.savemap");
field = new TextField();
listener = cons;
Platform.instance.addDialog(field);
shown(() -> {
content().clear();
content().label(() ->{
Map map = world.maps().getMap(field.getText());
if(map != null){
if(map.custom){
return "$text.editor.overwrite";
}else{
return "$text.editor.failoverwrite";
}
}
return "";
}).colspan(2);
content().row();
content().add("$text.editor.mapname").padRight(14f);
content().add(field).size(220f, 48f);
});
buttons().defaults().size(200f, 50f).pad(2f);
buttons().addButton("$text.cancel", this::hide);
TextButton button = new TextButton("$text.save");
button.clicked(() -> {
if(!invalid()){
cons.accept(field.getText());
hide();
}
});
button.setDisabled(this::invalid);
buttons().add(button);
}
public void save(){
if(!invalid()){
listener.accept(field.getText());
}else{
ui.showError("$text.editor.failoverwrite");
}
}
public void setFieldText(String text){
field.setText(text);
}
private boolean invalid(){
if(field.getText().isEmpty()){
return true;
}
Map map = world.maps().getMap(field.getText());
return map != null && !map.custom;
}
}

View File

@@ -1,328 +0,0 @@
package io.anuke.mindustry.mapeditor;
import com.badlogic.gdx.Input.Keys;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Colors;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.g2d.Batch;
import com.badlogic.gdx.input.GestureDetector;
import com.badlogic.gdx.input.GestureDetector.GestureListener;
import com.badlogic.gdx.math.Bresenham2;
import com.badlogic.gdx.math.GridPoint2;
import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.utils.ScissorStack;
import com.badlogic.gdx.utils.Array;
import io.anuke.mindustry.ui.GridImage;
import io.anuke.mindustry.world.ColorMapper;
import io.anuke.ucore.core.Core;
import io.anuke.ucore.core.Graphics;
import io.anuke.ucore.core.Inputs;
import io.anuke.ucore.graphics.Draw;
import io.anuke.ucore.graphics.Lines;
import io.anuke.ucore.graphics.Pixmaps;
import io.anuke.ucore.scene.Element;
import io.anuke.ucore.scene.event.InputEvent;
import io.anuke.ucore.scene.event.InputListener;
import io.anuke.ucore.scene.event.Touchable;
import io.anuke.ucore.scene.ui.TextField;
import io.anuke.ucore.scene.ui.layout.Unit;
import io.anuke.ucore.util.Mathf;
import io.anuke.ucore.util.Tmp;
import static io.anuke.mindustry.Vars.ui;
public class MapView extends Element implements GestureListener{
private MapEditor editor;
private EditorTool tool = EditorTool.pencil;
private OperationStack stack = new OperationStack();
private DrawOperation op;
private Pixmap current;
private Bresenham2 br = new Bresenham2();
private boolean updated = false;
private float offsetx, offsety;
private float zoom = 1f;
private boolean grid = false;
private GridImage image = new GridImage(0, 0);
private Vector2 vec = new Vector2();
private Rectangle rect = new Rectangle();
private boolean drawing;
private int lastx, lasty;
private int startx, starty;
public void setTool(EditorTool tool){
this.tool = tool;
}
public EditorTool getTool() {
return tool;
}
public void clearStack(){
stack.clear();
current = null;
}
public OperationStack getStack() {
return stack;
}
public void setGrid(boolean grid) {
this.grid = grid;
}
public boolean isGrid() {
return grid;
}
public void push(Pixmap previous, Pixmap add){
DrawOperation op = new DrawOperation(editor.pixmap());
op.add(previous, add);
stack.add(op);
this.current = add;
}
public void undo(){
if(stack.canUndo()){
stack.undo();
editor.updateTexture();
}
}
public void redo(){
if(stack.canRedo()){
stack.redo();
editor.updateTexture();
}
}
public MapView(MapEditor editor){
this.editor = editor;
Inputs.addProcessor(0, new GestureDetector(20, 0.5f, 2, 0.15f, this));
setTouchable(Touchable.enabled);
addListener(new InputListener(){
@Override
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
if(pointer != 0){
return false;
}
if(current == null){
current = Pixmaps.copy(editor.pixmap());
}
updated = false;
GridPoint2 p = project(x, y);
lastx = p.x;
lasty = p.y;
startx = p.x;
starty = p.y;
tool.touched(editor, p.x, p.y);
if(tool.edit){
updated = true;
ui.editor.resetSaved();
}
op = new DrawOperation(editor.pixmap());
drawing = true;
return true;
}
@Override
public void touchUp (InputEvent event, float x, float y, int pointer, int button) {
drawing = false;
GridPoint2 p = project(x, y);
if(tool == EditorTool.line){
ui.editor.resetSaved();
Array<GridPoint2> points = br.line(startx, starty, p.x, p.y);
for(GridPoint2 point : points){
editor.draw(point.x, point.y);
}
updated = true;
}
if(updated){
if(op == null) op = new DrawOperation(editor.pixmap());
Pixmap next = Pixmaps.copy(editor.pixmap());
op.add(current, next);
current = null;
stack.add(op);
op = null;
}
}
@Override
public void touchDragged (InputEvent event, float x, float y, int pointer) {
GridPoint2 p = project(x, y);
if(drawing && tool == EditorTool.pencil){
ui.editor.resetSaved();
Array<GridPoint2> points = br.line(lastx, lasty, p.x, p.y);
for(GridPoint2 point : points){
editor.draw(point.x, point.y);
}
updated = true;
}
lastx = p.x;
lasty = p.y;
}
});
}
@Override
public void act(float delta){
super.act(delta);
if(Core.scene.getKeyboardFocus() == null || !(Core.scene.getKeyboardFocus() instanceof TextField) &&
!Inputs.keyDown(Keys.CONTROL_LEFT)) {
float ax = Inputs.getAxis("move_x");
float ay = Inputs.getAxis("move_y");
offsetx -= ax * 15f / zoom;
offsety -= ay * 15f / zoom;
}
if(ui.editor.hasPane()) return;
zoom += Inputs.scroll()/10f * zoom;
clampZoom();
}
private void clampZoom(){
zoom = Mathf.clamp(zoom, 0.2f, 12f);
}
private GridPoint2 project(float x, float y){
float ratio = 1f / ((float)editor.pixmap().getWidth() / editor.pixmap().getHeight());
float size = Math.min(width, height);
float sclwidth = size * zoom;
float sclheight = size * zoom * ratio;
x = (x - getWidth()/2 + sclwidth/2 - offsetx*zoom) / sclwidth * editor.texture().getWidth();
y = (y - getHeight()/2 + sclheight/2 - offsety*zoom) / sclheight * editor.texture().getHeight();
return Tmp.g1.set((int)x, editor.texture().getHeight() - 1 - (int)y);
}
private Vector2 unproject(int x, int y){
float ratio = 1f / ((float)editor.pixmap().getWidth() / editor.pixmap().getHeight());
float size = Math.min(width, height);
float sclwidth = size * zoom;
float sclheight = size * zoom * ratio;
float px = ((float)x / editor.texture().getWidth()) * sclwidth + offsetx*zoom - sclwidth/2 + getWidth()/2;
float py = (float)((float)(editor.texture().getHeight() - 1 - y) / editor.texture().getHeight()) * sclheight
+ offsety*zoom - sclheight/2 + getHeight()/2;
return vec.set(px, py);
}
@Override
public void draw(Batch batch, float alpha){
float ratio = 1f / ((float)editor.pixmap().getWidth() / editor.pixmap().getHeight());
float size = Math.min(width, height);
float sclwidth = size * zoom;
float sclheight = size * zoom * ratio;
float centerx = x + width/2 + offsetx * zoom;
float centery = y + height/2 + offsety * zoom;
image.setImageSize(editor.pixmap().getWidth(), editor.pixmap().getHeight());
batch.flush();
boolean pop = ScissorStack.pushScissors(rect.set(x + width/2 - size/2, y + height/2 - size/2, size, size));
batch.draw(editor.texture(), centerx - sclwidth/2, centery - sclheight/2, sclwidth, sclheight);
if(grid){
Draw.color(Color.GRAY);
image.setBounds(centerx - sclwidth/2, centery - sclheight/2, sclwidth, sclheight);
image.draw(batch, alpha);
Draw.color();
}
if(tool == EditorTool.line && drawing){
Vector2 v1 = unproject(startx, starty).add(x, y);
float sx = v1.x, sy = v1.y;
Vector2 v2 = unproject(lastx, lasty).add(x, y);
Draw.color(Tmp.c1.set(ColorMapper.getColor(editor.getDrawBlock())));
Lines.stroke(Unit.dp.scl(3f * zoom));
Lines.line(sx, sy, v2.x, v2.y);
Lines.poly(sx, sy, 40, editor.getBrushSize() * zoom * 3);
Lines.poly(v2.x, v2.y, 40, editor.getBrushSize() * zoom * 3);
}
batch.flush();
if(pop) ScissorStack.popScissors();
Draw.color(Colors.get("accent"));
Lines.stroke(Unit.dp.scl(3f));
Lines.rect(x + width/2 - size/2, y + height/2 - size/2, size, size);
Draw.reset();
}
private boolean active(){
return Core.scene.getKeyboardFocus() != null
&& Core.scene.getKeyboardFocus().isDescendantOf(ui.editor)
&& ui.editor.isShown() && tool == EditorTool.zoom &&
Core.scene.hit(Graphics.mouse().x, Graphics.mouse().y, true) == this;
}
@Override
public boolean touchDown(float x, float y, int pointer, int button){
return false;
}
@Override
public boolean tap(float x, float y, int count, int button){
return false;
}
@Override
public boolean longPress(float x, float y){
return false;
}
@Override
public boolean fling(float velocityX, float velocityY, int button){
return false;
}
@Override
public boolean pan(float x, float y, float deltaX, float deltaY){
if(!active()) return false;
offsetx += deltaX / zoom;
offsety -= deltaY / zoom;
return false;
}
@Override
public boolean panStop(float x, float y, int pointer, int button){
return false;
}
@Override
public boolean zoom(float initialDistance, float distance){
if(!active()) return false;
float nzoom = distance - initialDistance;
zoom += nzoom / 10000f / Unit.dp.scl(1f) * zoom;
clampZoom();
return false;
}
@Override
public boolean pinch(Vector2 initialPointer1, Vector2 initialPointer2, Vector2 pointer1, Vector2 pointer2){
return false;
}
@Override
public void pinchStop(){
}
}

View File

@@ -1,55 +0,0 @@
package io.anuke.mindustry.mapeditor;
import com.badlogic.gdx.utils.Array;
public class OperationStack{
private final static int maxSize = 10;
private Array<DrawOperation> stack = new Array<>();
private int index = 0;
public OperationStack(){
}
public void clear(){
for(DrawOperation op : stack){
op.dispose();
}
stack.clear();
index = 0;
}
public void add(DrawOperation action){
stack.truncate(stack.size + index);
index = 0;
stack.add(action);
if(stack.size > maxSize){
stack.get(0).disposeFrom();
stack.removeIndex(0);
}
}
public boolean canUndo(){
return !(stack.size - 1 + index < 0);
}
public boolean canRedo(){
return !(index > -1 || stack.size + index < 0);
}
public void undo(){
if(!canUndo()) return;
stack.get(stack.size - 1 + index).undo();
index --;
}
public void redo(){
if(!canRedo()) return;
index ++;
stack.get(stack.size - 1 + index).redo();
}
}

View File

@@ -1,20 +1,19 @@
package io.anuke.mindustry.net;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.graphics.Pixmap.Format;
import com.badlogic.gdx.utils.ByteArray;
import com.badlogic.gdx.utils.TimeUtils;
import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.game.GameMode;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.io.Version;
import io.anuke.mindustry.resource.Upgrade;
import io.anuke.mindustry.resource.Weapon;
import io.anuke.mindustry.world.*;
import io.anuke.mindustry.world.Tile;
import io.anuke.mindustry.world.blocks.Blocks;
import io.anuke.mindustry.world.blocks.types.BlockPart;
import io.anuke.mindustry.world.blocks.types.Rock;
import io.anuke.ucore.core.Timers;
import io.anuke.ucore.entities.Entities;
import io.anuke.ucore.util.Bits;
import java.io.*;
import java.nio.ByteBuffer;
@@ -23,86 +22,6 @@ import static io.anuke.mindustry.Vars.*;
public class NetworkIO {
public static void writeMap(Map map, OutputStream os){
try(DataOutputStream stream = new DataOutputStream(os)){
stream.writeUTF(map.name);
stream.writeBoolean(map.oreGen);
stream.writeShort(map.getWidth());
stream.writeShort(map.getHeight());
int width = map.getWidth();
int cap = map.getWidth() * map.getHeight();
int pos = 0;
while(pos < cap){
int color = map.pixmap.getPixel(pos % width, pos / width);
byte id = ColorMapper.getColorID(color);
int length = 1;
while(true){
if(pos >= cap || length > 254){
break;
}
pos ++;
int next = map.pixmap.getPixel(pos % width, pos / width);
if(next != color){
pos --;
break;
}else{
length ++;
}
}
if(id == -1) id = 2;
stream.writeByte((byte)(length > 127 ? length - 256 : length));
stream.writeByte(id);
pos ++;
}
}catch (IOException e){
throw new RuntimeException(e);
}
}
public static Map loadMap(InputStream is){
try(DataInputStream stream = new DataInputStream(is)){
String name = stream.readUTF();
boolean ores = stream.readBoolean();
short width = stream.readShort();
short height = stream.readShort();
Pixmap pixmap = new Pixmap(width, height, Format.RGBA8888);
int pos = 0;
while(stream.available() > 0){
int length = stream.readByte();
byte id = stream.readByte();
if(length < 0) length += 256;
int color = ColorMapper.getColorByID(id);
for(int p = 0; p < length; p ++){
pixmap.drawPixel(pos % width, pos / width,color);
pos ++;
}
}
Map map = new Map();
map.name = name;
map.oreGen = ores;
map.custom = true;
map.pixmap = pixmap;
map.visible = false;
map.id = -1;
return map;
}catch (IOException e){
throw new RuntimeException(e);
}
}
public static void writeWorld(Player player, ByteArray upgrades, OutputStream os){
try(DataOutputStream stream = new DataOutputStream(os)){
@@ -112,7 +31,7 @@ public class NetworkIO {
//--GENERAL STATE--
stream.writeByte(state.mode.ordinal()); //gamemode
stream.writeByte(world.getMap().custom ? -1 : world.getMap().id); //map ID
stream.writeUTF(world.getMap().name); //map ID
stream.writeInt(state.wave); //wave
stream.writeFloat(state.wavetime); //wave countdown
@@ -136,87 +55,33 @@ public class NetworkIO {
//--MAP DATA--
//seed
stream.writeInt(world.getSeed());
int totalblocks = 0;
int totalrocks = 0;
//map size
stream.writeShort(world.width());
stream.writeShort(world.height());
for(int x = 0; x < world.width(); x ++){
for(int y = 0; y < world.height(); y ++){
Tile tile = world.tile(x, y);
if(tile.breakable()){
if(tile.block() instanceof Rock){
totalrocks ++;
}else{
totalblocks ++;
}
//TODO will break if block number gets over BYTE_MAX
stream.writeByte(tile.floor().id); //floor ID
stream.writeByte(tile.block().id); //block ID
if(tile.block() instanceof BlockPart){
stream.writeByte(tile.link);
}
}
}
//amount of rocks
stream.writeInt(totalrocks);
if(tile.entity != null){
stream.writeByte(Bits.packByte((byte)tile.getTeam().ordinal(), tile.getRotation()));
stream.writeShort((short)tile.entity.health); //health
//write all rocks
for(int x = 0; x < world.width(); x ++) {
for (int y = 0; y < world.height(); y++) {
Tile tile = world.tile(x, y);
if(tile.entity.inventory != null) tile.entity.inventory.write(stream);
if(tile.entity.power != null) tile.entity.power.write(stream);
if(tile.entity.liquid != null) tile.entity.liquid.write(stream);
if (tile.block() instanceof Rock) {
stream.writeInt(tile.packedPosition());
tile.entity.write(stream);
}
}
}
//tile amount
stream.writeInt(totalblocks);
for(int x = 0; x < world.width(); x ++){
for(int y = 0; y < world.height(); y ++){
Tile tile = world.tile(x, y);
if(tile.breakable() && !(tile.block() instanceof Rock)){
stream.writeInt(x + y*world.width()); //tile pos
//TODO will break if block number gets over BYTE_MAX
stream.writeByte(tile.block().id); //block ID
if(tile.block() instanceof BlockPart){
stream.writeByte(tile.link);
}
if(tile.entity != null){
stream.writeByte(tile.getRotation());
stream.writeByte(tile.getDump());
stream.writeByte(tile.getExtra());
stream.writeShort((short)tile.entity.health); //health
if(tile.entity.inventory != null) tile.entity.inventory.write(stream);
if(tile.entity.power != null) tile.entity.power.write(stream);
if(tile.entity.liquid != null) tile.entity.liquid.write(stream);
//timer data
//amount of active timers
byte times = 0;
for(; times < tile.entity.timer.getTimes().length; times ++){
if(tile.entity.timer.getTimes()[times] <= 1){
break;
}
}
stream.writeByte(times);
for(int i = 0; i < times; i ++){
stream.writeFloat(tile.entity.timer.getTimes()[i]);
}
tile.entity.write(stream);
}
}
}
}
@@ -228,6 +93,8 @@ public class NetworkIO {
/**Return whether a custom map is expected, and thus whether the client should wait for additional data.*/
public static void loadWorld(InputStream is){
//TODO !! use map name as the network map in Maps, so getMap() isn't null.
try(DataInputStream stream = new DataInputStream(is)){
float timerTime = stream.readFloat();
long timestamp = stream.readLong();
@@ -237,7 +104,7 @@ public class NetworkIO {
//general state
byte mode = stream.readByte();
byte mapid = stream.readByte();
String map = stream.readUTF();
int wave = stream.readInt();
float wavetime = stream.readFloat();
@@ -266,7 +133,7 @@ public class NetworkIO {
byte weapons = stream.readByte();
for(int i = 0; i < weapons; i ++){
control.upgrades().getWeapons().add((Weapon) Upgrade.getByID(stream.readByte()));
control.upgrades().getWeapons().add(Upgrade.getByID(stream.readByte()));
}
player.weaponLeft = player.weaponRight = control.upgrades().getWeapons().peek();
@@ -278,68 +145,44 @@ public class NetworkIO {
player.add();
//map
int width = stream.readShort();
int height = stream.readShort();
int seed = stream.readInt();
world.loadMap(world.maps().getMap(mapid), seed);
renderer.clearTiles();
player.set(world.getSpawnX(), world.getSpawnY());
Tile[][] tiles = world.createTiles(width, height);
for(int x = 0; x < world.width(); x ++){
for(int y = 0; y < world.height(); y ++){
Tile tile = world.tile(x, y);
byte floorid = stream.readByte();
byte blockid = stream.readByte();
//remove breakables like rocks
if(tile.breakable()){
world.tile(x, y).setBlock(Blocks.air);
}
}
}
Tile tile = new Tile(x, y, floorid, blockid);
int rocks = stream.readInt();
for(int i = 0; i < rocks; i ++){
int pos = stream.readInt();
Tile tile = world.tile(pos % world.width(), pos / world.width());
Block result = WorldGenerator.rocks.get(tile.floor());
if(result != null) tile.setBlock(result);
}
int tiles = stream.readInt();
for(int i = 0; i < tiles; i ++){
int pos = stream.readInt();
byte blockid = stream.readByte();
Tile tile = world.tile(pos % world.width(), pos / world.width());
tile.setBlock(Block.getByID(blockid));
if(tile.block() == Blocks.blockpart){
tile.link = stream.readByte();
}
if(tile.entity != null){
tile.setRotation(stream.readByte());
tile.setDump(stream.readByte());
tile.setExtra(stream.readByte());
short health = stream.readShort();
tile.entity.health = health;
if(tile.entity.inventory != null) tile.entity.inventory.read(stream);
if(tile.entity.power != null) tile.entity.power.read(stream);
if(tile.entity.liquid != null) tile.entity.liquid.read(stream);
byte timers = stream.readByte();
for(int time = 0; time < timers; time ++){
tile.entity.timer.getTimes()[time] = stream.readFloat();
if(tile.block() == Blocks.blockpart){
tile.link = stream.readByte();
}
tile.entity.read(stream);
if(tile.entity != null) {
byte tr = stream.readByte();
short health = stream.readShort();
tile.setTeam(Team.values()[Bits.getLeftByte(tr)]);
tile.setRotation(Bits.getRightByte(tr));
tile.entity.health = health;
if (tile.entity.inventory != null) tile.entity.inventory.read(stream);
if (tile.entity.power != null) tile.entity.power.read(stream);
if (tile.entity.liquid != null) tile.entity.liquid.read(stream);
tile.entity.read(stream);
}
tiles[x][y] = tile;
}
}
player.set(world.getSpawnX(), world.getSpawnY());
}catch (IOException e){
throw new RuntimeException(e);
}

View File

@@ -14,6 +14,7 @@ import io.anuke.mindustry.resource.Item;
import io.anuke.mindustry.world.Block;
import io.anuke.ucore.entities.Entities;
import io.anuke.ucore.entities.EntityGroup;
import io.anuke.ucore.util.IOUtils;
import java.nio.ByteBuffer;
@@ -64,8 +65,7 @@ public class Packets {
@Override
public void write(ByteBuffer buffer) {
buffer.putInt(Version.build);
buffer.put((byte)name.getBytes().length);
buffer.put(name.getBytes());
IOUtils.writeString(buffer, name);
buffer.put(android ? (byte)1 : 0);
buffer.putInt(color);
buffer.put(uuid);
@@ -74,10 +74,7 @@ public class Packets {
@Override
public void read(ByteBuffer buffer) {
version = buffer.getInt();
byte length = buffer.get();
byte[] bytes = new byte[length];
buffer.get(bytes);
name = new String(bytes);
name = IOUtils.readString(buffer);
android = buffer.get() == 1;
color = buffer.getInt();
uuid = new byte[8];
@@ -320,8 +317,7 @@ public class Packets {
}else{
buffer.putShort((short)-1);
}
buffer.putShort((short)text.getBytes().length);
buffer.put(text.getBytes());
IOUtils.writeString(buffer, text);
buffer.putInt(id);
}
@@ -333,12 +329,9 @@ public class Packets {
buffer.get(n);
name = new String(n);
}
short tlength = buffer.getShort();
byte[] t = new byte[tlength];
buffer.get(t);
text = IOUtils.readString(buffer);
id = buffer.getInt();
text = new String(t);
}
}
@@ -487,16 +480,12 @@ public class Packets {
@Override
public void write(ByteBuffer buffer) {
buffer.putShort((short)message.getBytes().length);
buffer.put(message.getBytes());
IOUtils.writeString(buffer, message);
}
@Override
public void read(ByteBuffer buffer) {
short length = buffer.getShort();
byte[] bytes = new byte[length];
buffer.get(bytes);
message = new String(bytes);
message = IOUtils.readString(buffer);
}
}

View File

@@ -4,12 +4,12 @@ import io.anuke.mindustry.Vars;
import io.anuke.mindustry.entities.Bullet;
import io.anuke.mindustry.entities.BulletType;
import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.entities.Unit;
import io.anuke.mindustry.graphics.Fx;
import io.anuke.mindustry.net.Net;
import io.anuke.mindustry.net.NetEvents;
import io.anuke.ucore.core.Effects;
import io.anuke.ucore.core.Effects.Effect;
import io.anuke.ucore.entities.Entity;
import io.anuke.ucore.util.Angles;
import io.anuke.ucore.util.Mathf;
import io.anuke.ucore.util.Translator;
@@ -125,7 +125,7 @@ public class Weapon extends Upgrade{
}
}
void bullet(Entity owner, float x, float y, float angle){
void bullet(Unit owner, float x, float y, float angle){
tr.trns(angle, 3f);
new Bullet(type, owner, x + tr.x, y + tr.y, angle).add();
}

View File

@@ -1,15 +1,13 @@
package io.anuke.mindustry.ui.dialogs;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.math.Vector2;
import io.anuke.mindustry.game.Difficulty;
import io.anuke.mindustry.game.GameMode;
import io.anuke.mindustry.world.Map;
import io.anuke.mindustry.io.Map;
import io.anuke.ucore.core.Core;
import io.anuke.ucore.core.Settings;
import io.anuke.ucore.core.Timers;
import io.anuke.ucore.scene.event.ClickListener;
import io.anuke.ucore.scene.event.InputEvent;
import io.anuke.ucore.scene.event.Touchable;
import io.anuke.ucore.scene.ui.*;
import io.anuke.ucore.scene.ui.layout.Stack;
@@ -21,7 +19,6 @@ import io.anuke.ucore.util.Mathf;
import static io.anuke.mindustry.Vars.*;
public class LevelDialog extends FloatingDialog{
private Map selectedMap = world.maps().getMap(0);
private ScrollPane pane;
public LevelDialog(){
@@ -88,10 +85,8 @@ public class LevelDialog extends FloatingDialog{
content().row();
int i = 0;
for(Map map : world.maps().list()){
if(!map.visible && !debug) continue;
for(Map map : world.maps().all()){
if(i % maxwidth == 0){
maps.row();
}
@@ -115,40 +110,16 @@ public class LevelDialog extends FloatingDialog{
Stack stack = new Stack();
Image back = new Image("white");
back.setColor(map.backgroundColor);
back.setColor(Color.valueOf("646464"));
ImageButton image = new ImageButton(new TextureRegion(map.texture), "togglemap");
image.row();
image.add(inset).width(images+6);
TextButton[] delete = new TextButton[1];
if(map.custom){
image.row();
delete[0] = image.addButton("Delete", () -> {
Timers.run(1f, () -> {
ui.showConfirm("$text.level.delete.title", Bundles.format("text.level.delete", Bundles.get("map."+map.name+".name", map.name)), () -> {
world.maps().removeMap(map);
reload();
Core.scene.setScrollFocus(pane);
});
});
}).width(images+16).padBottom(-10f).grow().get();
}
//TODO custom map delete button
Vector2 hit = new Vector2();
image.addListener(new ClickListener(){
public void clicked(InputEvent event, float x, float y){
image.localToStageCoordinates(hit.set(x, y));
if(delete[0] != null && (delete[0].getClickListener().isOver() || delete[0].getClickListener().isPressed()
|| (Core.scene.hit(hit.x, hit.y, true) != null &&
Core.scene.hit(hit.x, hit.y, true).isDescendantOf(delete[0])))){
return;
}
selectedMap = map;
hide();
control.playMap(selectedMap);
}
image.clicked(() -> {
hide();
control.playMap(map);
});
image.getImageCell().size(images);

View File

@@ -100,7 +100,7 @@ public class LoadDialog extends FloatingDialog{
button.defaults().padBottom(3);
button.row();
button.add(Bundles.format("text.save.map", color+slot.getMap().localized()));
button.add(Bundles.format("text.save.map", color+slot.getMap().meta.name()));
button.row();
button.add(Bundles.get("text.level.mode") + " " +color+ slot.getMode());
button.row();

View File

@@ -50,7 +50,7 @@ public class PausedDialog extends FloatingDialog{
content().row();
content().addButton("$text.savegame", () -> {
save.show();
}).disabled(b -> world.getMap().id == -1);
});
content().row();
content().addButton("$text.loadgame", () -> {
@@ -93,7 +93,6 @@ public class PausedDialog extends FloatingDialog{
imagebutton sa = new imagebutton("icon-save", isize, save::show);
sa.text("$text.save").padTop(4f);
sa.cell.disabled(b -> world.getMap().id == -1);
content().row();

View File

@@ -121,8 +121,6 @@ public class DebugFragment implements Fragment {
"players: " + playerGroup.size(),
"tiles: " + tileGroup.size(),
"time: " + Timers.time(),
world.getCore() != null && world.getCore().entity != null ? "core.health: " + world.getCore().entity.health : "",
"core: " + world.getCore(),
"state.gameover: " + state.gameOver,
"state: " + state.getState(),
!Net.server() ? clientDebug.getOut() : serverDebug.getOut()

View File

@@ -62,7 +62,7 @@ public class MenuFragment implements Fragment{
new imagebutton("icon-play-2", isize, ui.levels::show).text("$text.play").padTop(4f);
new imagebutton("icon-tutorial", isize, () -> control.playMap(world.maps().getMap("tutorial"))).text("$text.tutorial").padTop(4f);
new imagebutton("icon-tutorial", isize, () -> control.playMap(world.maps().getByName("tutorial"))).text("$text.tutorial").padTop(4f);
new imagebutton("icon-load", isize, ui.load::show).text("$text.load").padTop(4f);
@@ -120,7 +120,7 @@ public class MenuFragment implements Fragment{
}
}));
dialog.content().add(new MenuButton("icon-tutorial", "$text.tutorial", ()-> {
control.playMap(world.maps().getMap("tutorial"));
control.playMap(world.maps().getByName("tutorial"));
dialog.hide();
}));

View File

@@ -6,9 +6,7 @@ import com.badlogic.gdx.utils.IntIntMap;
import com.badlogic.gdx.utils.IntMap;
import com.badlogic.gdx.utils.IntMap.Entry;
import com.badlogic.gdx.utils.ObjectIntMap;
import io.anuke.mindustry.world.blocks.Blocks;
import io.anuke.mindustry.world.blocks.SpecialBlocks;
public class ColorMapper{
/**maps color IDs to their actual RGBA8888 colors*/
@@ -19,8 +17,6 @@ public class ColorMapper{
private static ObjectIntMap<Block> reverseColors = new ObjectIntMap<>();
private static Array<BlockPair> pairs = new Array<>();
private static IntMap<BlockPair> colors = map(
"ff0000", pair(Blocks.dirt, SpecialBlocks.enemySpawn),
"00ff00", pair(Blocks.stone, SpecialBlocks.playerSpawn),
"323232", pair(Blocks.stone),
"646464", pair(Blocks.stone, Blocks.stoneblock),
"50965a", pair(Blocks.grass),

View File

@@ -1,10 +0,0 @@
package io.anuke.mindustry.world;
public class Map{
public String name;
public String author;
public String description;
public boolean visible = true;
public boolean custom = false;
public boolean oreGen = true;
}

View File

@@ -5,7 +5,6 @@ import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.utils.Array;
import io.anuke.mindustry.entities.Player;
import io.anuke.mindustry.entities.Units;
import io.anuke.mindustry.game.SpawnPoint;
import io.anuke.mindustry.game.Team;
import io.anuke.mindustry.graphics.Fx;
import io.anuke.mindustry.resource.ItemStack;
@@ -93,13 +92,6 @@ public class Placement {
}
public static boolean validPlace(Team team, int x, int y, Block type){
for(int i = 0; i < world.getSpawns().size; i ++){
SpawnPoint spawn = world.getSpawns().get(i);
if(Vector2.dst(x * tilesize, y * tilesize, spawn.start.worldx(), spawn.start.worldy()) < enemyspawnspace){
return false;
}
}
Recipe recipe = Recipes.getByResult(type);
if(recipe == null || !state.inventory.hasItems(recipe.requirements)){
@@ -157,8 +149,9 @@ public class Placement {
}
}
//TODO make this work!
public static boolean isSpawnPoint(Tile tile){
return tile != null && tile.x == world.getCore().x && tile.y == world.getCore().y - 2;
return false;
}
public static boolean validBreak(Team team, int x, int y){

View File

@@ -37,24 +37,25 @@ public class Tile{
this.x = (short)x;
this.y = (short)y;
}
public Tile(int x, int y, Block floor){
public Tile(int x, int y, byte floor, byte wall){
this(x, y);
iSetFloor(floor);
this.floor = floor;
this.wall = wall;
}
public Tile(int x, int y, byte floor, byte wall, byte rotation, byte team){
this(x, y);
this.floor = floor;
this.wall = wall;
this.rotation = rotation;
this.team = team;
}
public int packedPosition(){
return x + y * world.width();
}
private void iSetFloor(Block floor){
this.floor = (byte)floor.id;
}
private void iSetBlock(Block wall){
this.wall = (byte)wall.id;
}
public byte getWallID(){
return wall;
}
@@ -130,23 +131,23 @@ public class Tile{
public void setBlock(Block type, int rotation){
synchronized (tileSetLock) {
if(rotation < 0) rotation = (-rotation + 2);
iSetBlock(type);
setRotation((byte) (rotation % 4));
this.wall = (byte)type.id;
this.link = 0;
setRotation((byte) (rotation % 4));
changed();
}
}
public void setBlock(Block type){
synchronized (tileSetLock) {
iSetBlock(type);
this.wall = (byte)type.id;
this.link = 0;
changed();
}
}
public void setFloor(Block type){
iSetFloor(type);
this.floor = (byte)type.id;
}
public void setRotation(byte rotation){

View File

@@ -1,19 +1,14 @@
package io.anuke.mindustry.world;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.Pixmap;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.ObjectMap;
import io.anuke.mindustry.game.SpawnPoint;
import io.anuke.mindustry.world.ColorMapper.BlockPair;
import io.anuke.mindustry.io.MapTileData;
import io.anuke.mindustry.io.MapTileData.TileData;
import io.anuke.mindustry.world.blocks.Blocks;
import io.anuke.mindustry.world.blocks.SpecialBlocks;
import io.anuke.ucore.graphics.Hue;
import io.anuke.ucore.noise.Noise;
import io.anuke.ucore.util.Mathf;
import static io.anuke.mindustry.Vars.world;
public class WorldGenerator {
public static final ObjectMap<Block, Block> rocks = new ObjectMap<Block, Block>(){{
put(Blocks.stone, Blocks.rock);
@@ -22,67 +17,21 @@ public class WorldGenerator {
put(Blocks.blackstone, Blocks.blackrock);
}};
/**Returns the core (starting) block. Should fill spawns with the correct spawnpoints.*/
public static void generate(Tile[][] tiles, Map map){
/**Should fill spawns with the correct spawnpoints.*/
public static void generate(Tile[][] tiles, MapTileData data){
Noise.setSeed(world.getSeed());
for(int x = 0; x < pixmap.getWidth(); x ++){
for(int y = 0; y < pixmap.getHeight(); y ++){
Block floor = Blocks.stone;
Block block = Blocks.air;
int color = pixmap.getPixel(x, pixmap.getHeight()-1-y);
BlockPair pair = ColorMapper.get(color);
if(pair != null){
block = pair.wall;
floor = pair.floor;
}
if(block == SpecialBlocks.playerSpawn){
block = Blocks.air;
core = world.tile(x, y);
}else if(block == SpecialBlocks.enemySpawn){
block = Blocks.air;
spawns.add(new SpawnPoint(tiles[x][y]));
}
if(block == Blocks.air && Mathf.chance(0.025) && rocks.containsKey(floor)){
block = rocks.get(floor);
}
if(world.getMap().oreGen && (floor == Blocks.stone || floor == Blocks.grass || floor == Blocks.blackstone ||
floor == Blocks.snow || floor == Blocks.sand)){
if(Noise.nnoise(x, y, 8, 1) > 0.21){
floor = Blocks.iron;
}
if(Noise.nnoise(x, y, 6, 1) > 0.237){
floor = Blocks.coal;
}
if(Noise.nnoise(x + 9999, y + 9999, 8, 1) > 0.27){
floor = Blocks.titanium;
}
if(Noise.nnoise(x + 99999, y + 99999, 7, 1) > 0.259){
floor = Blocks.uranium;
}
}
if(color == Hue.rgb(Color.PURPLE)){
//TODO place unit here
//if(!Vars.android) new BaseUnit(UnitTypes.target).set(x * tilesize, y * tilesize).add();
floor = Blocks.stone;
}
tiles[x][y].setBlock(block, 0);
tiles[x][y].setFloor(floor);
for(int x = 0; x < data.width(); x ++){
for(int y = 0; y < data.height(); y ++){
TileData tile = data.read();
tiles[x][y] = new Tile(x, y, tile.floor, tile.wall, tile.rotation, tile.team);
//TODO ores, plants, extra decoration?
}
}
for(int x = 0; x < pixmap.getWidth(); x ++){
for(int y = 0; y < pixmap.getHeight(); y ++) {
for(int x = 0; x < data.width(); x ++){
for(int y = 0; y < data.height(); y ++) {
tiles[x][y].updateOcclusion();
}
}

View File

@@ -229,7 +229,7 @@ public class Turret extends Block{
}
protected void bullet(Tile tile, float angle){
new Bullet(bullet, tile.entity, tile.drawx() + tr.x, tile.drawy() + tr.y, angle).add();
new Bullet(bullet, tile.entity, tile.getTeam(), tile.drawx() + tr.x, tile.drawy() + tr.y, angle).add();
}
public static class TurretEntity extends TileEntity{

View File

@@ -6,6 +6,7 @@ import io.anuke.mindustry.world.Tile;
import static io.anuke.mindustry.Vars.debug;
import static io.anuke.mindustry.Vars.state;
import static io.anuke.mindustry.Vars.world;
public class CoreBlock extends StorageBlock {
protected int capacity = 1000;
@@ -25,6 +26,12 @@ public class CoreBlock extends StorageBlock {
return debug ? 0 : amount;
}
public void onDestroyed(Tile tile){
//TODO more dramatic effects
super.onDestroyed(tile);
world.getAllyCores().removeValue(tile, true);
}
@Override
public void handleItem(Item item, Tile tile, Tile source){
if(Net.server() || !Net.active()) state.inventory.addItem(item, 1);