New map format, completely broke loading or playing
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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.*/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
@@ -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) -> {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
20
core/src/io/anuke/mindustry/io/Map.java
Normal file
20
core/src/io/anuke/mindustry/io/Map.java
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -3,4 +3,6 @@ package io.anuke.mindustry.io;
|
||||
/**Reads and writes map files.*/
|
||||
public class MapIO {
|
||||
//TODO implementation
|
||||
|
||||
|
||||
}
|
||||
|
||||
32
core/src/io/anuke/mindustry/io/MapMeta.java
Normal file
32
core/src/io/anuke/mindustry/io/MapMeta.java
Normal 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");
|
||||
}
|
||||
}
|
||||
75
core/src/io/anuke/mindustry/io/MapTileData.java
Normal file
75
core/src/io/anuke/mindustry/io/MapTileData.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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){
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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(){
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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();
|
||||
}));
|
||||
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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){
|
||||
|
||||
@@ -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){
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user