Merge branch 'master' of https://github.com/Anuken/Mindustry
@@ -8,7 +8,7 @@ buildscript{
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies{
|
dependencies{
|
||||||
classpath 'com.android.tools.build:gradle:3.4.0'
|
classpath 'com.android.tools.build:gradle:3.4.1'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,27 +166,4 @@ task run(type: Exec){
|
|||||||
|
|
||||||
def adb = path + "/platform-tools/adb"
|
def adb = path + "/platform-tools/adb"
|
||||||
commandLine "$adb", 'shell', 'am', 'start', '-n', 'io.anuke.mindustry/io.anuke.mindustry.AndroidLauncher'
|
commandLine "$adb", 'shell', 'am', 'start', '-n', 'io.anuke.mindustry/io.anuke.mindustry.AndroidLauncher'
|
||||||
}
|
}
|
||||||
|
|
||||||
// sets up the Android Idea project, using the old Ant based build.
|
|
||||||
idea{
|
|
||||||
module{
|
|
||||||
sourceDirs += file("src")
|
|
||||||
scopes = [COMPILE: [plus: [project.configurations.compile]]]
|
|
||||||
|
|
||||||
iml{
|
|
||||||
withXml{
|
|
||||||
def node = it.asNode()
|
|
||||||
def builder = NodeBuilder.newInstance()
|
|
||||||
builder.current = node
|
|
||||||
builder.component(name: "FacetManager"){
|
|
||||||
facet(type: "android", name: "Android"){
|
|
||||||
configuration{
|
|
||||||
option(name: "UPDATE_PROPERTY_FILES", value: "true")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -15,16 +15,15 @@ import io.anuke.arc.backends.android.surfaceview.AndroidApplication;
|
|||||||
import io.anuke.arc.backends.android.surfaceview.AndroidApplicationConfiguration;
|
import io.anuke.arc.backends.android.surfaceview.AndroidApplicationConfiguration;
|
||||||
import io.anuke.arc.files.FileHandle;
|
import io.anuke.arc.files.FileHandle;
|
||||||
import io.anuke.arc.function.Consumer;
|
import io.anuke.arc.function.Consumer;
|
||||||
|
import io.anuke.arc.function.Predicate;
|
||||||
import io.anuke.arc.scene.ui.layout.Unit;
|
import io.anuke.arc.scene.ui.layout.Unit;
|
||||||
import io.anuke.arc.util.Strings;
|
import io.anuke.arc.util.Strings;
|
||||||
import io.anuke.arc.util.serialization.Base64Coder;
|
import io.anuke.arc.util.serialization.Base64Coder;
|
||||||
import io.anuke.mindustry.core.Platform;
|
import io.anuke.mindustry.core.Platform;
|
||||||
import io.anuke.mindustry.game.Saves.SaveSlot;
|
import io.anuke.mindustry.game.Saves.SaveSlot;
|
||||||
import io.anuke.mindustry.io.SaveIO;
|
import io.anuke.mindustry.io.SaveIO;
|
||||||
import io.anuke.mindustry.net.Net;
|
import io.anuke.mindustry.net.*;
|
||||||
import io.anuke.mindustry.ui.dialogs.FileChooser;
|
import io.anuke.mindustry.ui.dialogs.FileChooser;
|
||||||
import io.anuke.mindustry.net.ArcNetClient;
|
|
||||||
import io.anuke.mindustry.net.ArcNetServer;
|
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -72,10 +71,10 @@ public class AndroidLauncher extends AndroidApplication{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void showFileChooser(String text, String content, Consumer<FileHandle> cons, boolean open, String filetype){
|
public void showFileChooser(String text, String content, Consumer<FileHandle> cons, boolean open, Predicate<String> filetype){
|
||||||
chooser = new FileChooser(text, file -> file.extension().equalsIgnoreCase(filetype), open, cons);
|
chooser = new FileChooser(text, file -> filetype.test(file.extension().toLowerCase()), open, cons);
|
||||||
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.M || (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED &&
|
if(Build.VERSION.SDK_INT < Build.VERSION_CODES.M || (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED &&
|
||||||
checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)){
|
checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)){
|
||||||
chooser.show();
|
chooser.show();
|
||||||
chooser = null;
|
chooser = null;
|
||||||
}else{
|
}else{
|
||||||
@@ -157,7 +156,7 @@ public class AndroidLauncher extends AndroidApplication{
|
|||||||
SaveSlot slot = control.saves.importSave(file);
|
SaveSlot slot = control.saves.importSave(file);
|
||||||
ui.load.runLoadSave(slot);
|
ui.load.runLoadSave(slot);
|
||||||
}catch(IOException e){
|
}catch(IOException e){
|
||||||
ui.showError(Core.bundle.format("save.import.fail", Strings.parseException(e, false)));
|
ui.showError(Core.bundle.format("save.import.fail", Strings.parseException(e, true)));
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
ui.showError("$save.import.invalid");
|
ui.showError("$save.import.invalid");
|
||||||
|
|||||||
@@ -15,8 +15,6 @@ buildscript{
|
|||||||
}
|
}
|
||||||
|
|
||||||
allprojects{
|
allprojects{
|
||||||
apply plugin: "idea"
|
|
||||||
|
|
||||||
version = 'release'
|
version = 'release'
|
||||||
|
|
||||||
ext{
|
ext{
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 118 B |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 7.0 KiB |
BIN
core/assets-raw/sprites_replacement/blocks/environment/edge.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 603 B |
BIN
core/assets-raw/sprites_replacement/blocks/environment/spawn.png
Normal file
|
After Width: | Height: | Size: 221 B |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
@@ -219,6 +219,9 @@ editor.teams = Teams
|
|||||||
editor.elevation = Elevation
|
editor.elevation = Elevation
|
||||||
editor.errorload = Error loading file:\n[accent]{0}
|
editor.errorload = Error loading file:\n[accent]{0}
|
||||||
editor.errorsave = Error saving file:\n[accent]{0}
|
editor.errorsave = Error saving file:\n[accent]{0}
|
||||||
|
editor.errorimage = That's an image, not a map. Don't go around changing extensions expecting it to work.\n\nIf you want to import a legacy map, use the 'import legacy map' button in the editor.
|
||||||
|
editor.errorlegacy = This map is too old, and uses a legacy map format that is no longer supported.
|
||||||
|
editor.errorheader = This map file is either not valid or corrupt.
|
||||||
editor.errorname = Map has no name defined.
|
editor.errorname = Map has no name defined.
|
||||||
editor.update = Update
|
editor.update = Update
|
||||||
editor.randomize = Randomize
|
editor.randomize = Randomize
|
||||||
@@ -271,6 +274,8 @@ filter.option.wall = Wall
|
|||||||
filter.option.ore = Ore
|
filter.option.ore = Ore
|
||||||
filter.option.floor2 = Secondary Floor
|
filter.option.floor2 = Secondary Floor
|
||||||
filter.option.threshold2 = Secondary Threshold
|
filter.option.threshold2 = Secondary Threshold
|
||||||
|
filter.option.radius = Radius
|
||||||
|
filter.option.percentile = Percentile
|
||||||
width = Width:
|
width = Width:
|
||||||
height = Height:
|
height = Height:
|
||||||
menu = Menu
|
menu = Menu
|
||||||
@@ -426,6 +431,7 @@ category.shooting = Shooting
|
|||||||
category.optional = Optional Enhancements
|
category.optional = Optional Enhancements
|
||||||
setting.landscape.name = Lock Landscape
|
setting.landscape.name = Lock Landscape
|
||||||
setting.shadows.name = Shadows
|
setting.shadows.name = Shadows
|
||||||
|
setting.linear.name = Linear Filtering
|
||||||
setting.animatedwater.name = Animated Water
|
setting.animatedwater.name = Animated Water
|
||||||
setting.animatedshields.name = Animated Shields
|
setting.animatedshields.name = Animated Shields
|
||||||
setting.antialias.name = Antialias[LIGHT_GRAY] (requires restart)[]
|
setting.antialias.name = Antialias[LIGHT_GRAY] (requires restart)[]
|
||||||
@@ -801,7 +807,7 @@ block.spectre.name = Spectre
|
|||||||
block.meltdown.name = Meltdown
|
block.meltdown.name = Meltdown
|
||||||
block.container.name = Container
|
block.container.name = Container
|
||||||
block.launch-pad.name = Launch Pad
|
block.launch-pad.name = Launch Pad
|
||||||
block.launch-pad.description = Launches batches of items without any need for a core launch. Unfinished.
|
block.launch-pad.description = Launches batches of items without any need for a core launch.
|
||||||
block.launch-pad-large.name = Large Launch Pad
|
block.launch-pad-large.name = Large Launch Pad
|
||||||
team.blue.name = blue
|
team.blue.name = blue
|
||||||
team.red.name = red
|
team.red.name = red
|
||||||
|
|||||||
BIN
core/assets/maps/impact0078.msav
Normal file
BIN
core/assets/maps/islands.msav
Normal file
BIN
core/assets/maps/labyrinth.msav
Normal file
BIN
core/assets/maps/maze.msav
Normal file
BIN
core/assets/maps/saltcrags.msav
Normal file
BIN
core/assets/maps/shoreline.msav
Normal file
|
Before Width: | Height: | Size: 702 B After Width: | Height: | Size: 701 B |
|
Before Width: | Height: | Size: 1.2 MiB After Width: | Height: | Size: 1.2 MiB |
|
Before Width: | Height: | Size: 274 KiB After Width: | Height: | Size: 274 KiB |
|
Before Width: | Height: | Size: 1.2 MiB After Width: | Height: | Size: 301 KiB |
|
Before Width: | Height: | Size: 405 KiB After Width: | Height: | Size: 403 KiB |
|
Before Width: | Height: | Size: 307 KiB After Width: | Height: | Size: 310 KiB |
|
Before Width: | Height: | Size: 685 KiB After Width: | Height: | Size: 293 KiB |
|
Before Width: | Height: | Size: 417 KiB |
@@ -105,6 +105,8 @@ public class Vars{
|
|||||||
public static FileHandle screenshotDirectory;
|
public static FileHandle screenshotDirectory;
|
||||||
/** data subdirectory used for custom mmaps */
|
/** data subdirectory used for custom mmaps */
|
||||||
public static FileHandle customMapDirectory;
|
public static FileHandle customMapDirectory;
|
||||||
|
/** tmp subdirectory for map conversion */
|
||||||
|
public static FileHandle tmpDirectory;
|
||||||
/** data subdirectory used for saves */
|
/** data subdirectory used for saves */
|
||||||
public static FileHandle saveDirectory;
|
public static FileHandle saveDirectory;
|
||||||
/** old map file extension, for conversion */
|
/** old map file extension, for conversion */
|
||||||
@@ -206,5 +208,6 @@ public class Vars{
|
|||||||
screenshotDirectory = dataDirectory.child("screenshots/");
|
screenshotDirectory = dataDirectory.child("screenshots/");
|
||||||
customMapDirectory = dataDirectory.child("maps/");
|
customMapDirectory = dataDirectory.child("maps/");
|
||||||
saveDirectory = dataDirectory.child("saves/");
|
saveDirectory = dataDirectory.child("saves/");
|
||||||
|
tmpDirectory = dataDirectory.child("tmp/");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,7 @@ import io.anuke.arc.collection.IntArray;
|
|||||||
import io.anuke.arc.collection.IntQueue;
|
import io.anuke.arc.collection.IntQueue;
|
||||||
import io.anuke.arc.math.geom.Geometry;
|
import io.anuke.arc.math.geom.Geometry;
|
||||||
import io.anuke.arc.math.geom.Point2;
|
import io.anuke.arc.math.geom.Point2;
|
||||||
import io.anuke.arc.util.Structs;
|
import io.anuke.arc.util.*;
|
||||||
import io.anuke.arc.util.Time;
|
|
||||||
import io.anuke.mindustry.game.EventType.TileChangeEvent;
|
import io.anuke.mindustry.game.EventType.TileChangeEvent;
|
||||||
import io.anuke.mindustry.game.EventType.WorldLoadEvent;
|
import io.anuke.mindustry.game.EventType.WorldLoadEvent;
|
||||||
import io.anuke.mindustry.game.Team;
|
import io.anuke.mindustry.game.Team;
|
||||||
@@ -40,6 +39,10 @@ public class Pathfinder{
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void updateSolid(Tile tile){
|
||||||
|
update(tile, tile.getTeam());
|
||||||
|
}
|
||||||
|
|
||||||
public void update(){
|
public void update(){
|
||||||
if(Net.client() || paths == null) return;
|
if(Net.client() || paths == null) return;
|
||||||
|
|
||||||
@@ -95,6 +98,10 @@ public class Pathfinder{
|
|||||||
if(paths != null && paths[team.ordinal()] != null && paths[team.ordinal()].weights != null){
|
if(paths != null && paths[team.ordinal()] != null && paths[team.ordinal()].weights != null){
|
||||||
PathData path = paths[team.ordinal()];
|
PathData path = paths[team.ordinal()];
|
||||||
|
|
||||||
|
if(!path.frontier.isEmpty()){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//impassable tiles have a weight of float.max
|
//impassable tiles have a weight of float.max
|
||||||
if(!passable(tile, team)){
|
if(!passable(tile, team)){
|
||||||
path.weights[tile.x][tile.y] = Float.MAX_VALUE;
|
path.weights[tile.x][tile.y] = Float.MAX_VALUE;
|
||||||
|
|||||||
@@ -14,12 +14,13 @@ import io.anuke.mindustry.entities.type.BaseUnit;
|
|||||||
import io.anuke.mindustry.game.EventType.WorldLoadEvent;
|
import io.anuke.mindustry.game.EventType.WorldLoadEvent;
|
||||||
import io.anuke.mindustry.game.SpawnGroup;
|
import io.anuke.mindustry.game.SpawnGroup;
|
||||||
import io.anuke.mindustry.net.Net;
|
import io.anuke.mindustry.net.Net;
|
||||||
|
import io.anuke.mindustry.world.Tile;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
public class WaveSpawner{
|
public class WaveSpawner{
|
||||||
private Array<FlyerSpawn> flySpawns = new Array<>();
|
private Array<FlyerSpawn> flySpawns = new Array<>();
|
||||||
private Array<GroundSpawn> groundSpawns = new Array<>();
|
private Array<Tile> groundSpawns = new Array<>();
|
||||||
private boolean spawning = false;
|
private boolean spawning = false;
|
||||||
|
|
||||||
public WaveSpawner(){
|
public WaveSpawner(){
|
||||||
@@ -30,6 +31,10 @@ public class WaveSpawner{
|
|||||||
return groundSpawns.size;
|
return groundSpawns.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Array<Tile> getGroundSpawns(){
|
||||||
|
return groundSpawns;
|
||||||
|
}
|
||||||
|
|
||||||
/** @return true if the player is near a ground spawn point. */
|
/** @return true if the player is near a ground spawn point. */
|
||||||
public boolean playerNear(){
|
public boolean playerNear(){
|
||||||
return groundSpawns.contains(g -> Mathf.dst(g.x * tilesize, g.y * tilesize, player.x, player.y) < state.rules.dropZoneRadius);
|
return groundSpawns.contains(g -> Mathf.dst(g.x * tilesize, g.y * tilesize, player.x, player.y) < state.rules.dropZoneRadius);
|
||||||
@@ -59,9 +64,9 @@ public class WaveSpawner{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
for(GroundSpawn spawn : groundSpawns){
|
for(Tile spawn : groundSpawns){
|
||||||
spawnX = spawn.x * tilesize;
|
spawnX = spawn.worldx();
|
||||||
spawnY = spawn.y * tilesize;
|
spawnY = spawn.worldy();
|
||||||
spread = tilesize * 2;
|
spread = tilesize * 2;
|
||||||
|
|
||||||
for(int i = 0; i < spawned; i++){
|
for(int i = 0; i < spawned; i++){
|
||||||
@@ -102,10 +107,7 @@ public class WaveSpawner{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void addSpawns(int x, int y){
|
private void addSpawns(int x, int y){
|
||||||
GroundSpawn spawn = new GroundSpawn();
|
groundSpawns.add(world.tile(x, y));
|
||||||
spawn.x = x;
|
|
||||||
spawn.y = y;
|
|
||||||
groundSpawns.add(spawn);
|
|
||||||
|
|
||||||
FlyerSpawn fspawn = new FlyerSpawn();
|
FlyerSpawn fspawn = new FlyerSpawn();
|
||||||
fspawn.angle = Angles.angle(world.width() / 2f, world.height() / 2f, x, y);
|
fspawn.angle = Angles.angle(world.width() / 2f, world.height() / 2f, x, y);
|
||||||
|
|||||||
@@ -114,6 +114,9 @@ public class Blocks implements ContentList{
|
|||||||
}
|
}
|
||||||
|
|
||||||
spawn = new OverlayFloor("spawn"){
|
spawn = new OverlayFloor("spawn"){
|
||||||
|
{
|
||||||
|
variants = 0;
|
||||||
|
}
|
||||||
public void draw(Tile tile){}
|
public void draw(Tile tile){}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -496,19 +499,7 @@ public class Blocks implements ContentList{
|
|||||||
GenericCrafterEntity entity = tile.entity();
|
GenericCrafterEntity entity = tile.entity();
|
||||||
|
|
||||||
Draw.rect(reg(bottomRegion), tile.drawx(), tile.drawy());
|
Draw.rect(reg(bottomRegion), tile.drawx(), tile.drawy());
|
||||||
|
|
||||||
float progress = 0.5f;
|
|
||||||
|
|
||||||
Shaders.build.region = reg(weaveRegion);
|
|
||||||
Shaders.build.progress = progress;
|
|
||||||
Shaders.build.color.set(Pal.accent);
|
|
||||||
Shaders.build.color.a = entity.warmup;
|
|
||||||
Shaders.build.time = -entity.totalProgress / 10f;
|
|
||||||
|
|
||||||
Draw.shader(Shaders.build, false);
|
|
||||||
Shaders.build.apply();
|
|
||||||
Draw.rect(reg(weaveRegion), tile.drawx(), tile.drawy(), entity.totalProgress);
|
Draw.rect(reg(weaveRegion), tile.drawx(), tile.drawy(), entity.totalProgress);
|
||||||
Draw.shader();
|
|
||||||
|
|
||||||
Draw.color(Pal.accent);
|
Draw.color(Pal.accent);
|
||||||
Draw.alpha(entity.warmup);
|
Draw.alpha(entity.warmup);
|
||||||
@@ -940,7 +931,7 @@ public class Blocks implements ContentList{
|
|||||||
itemCapacity = 120;
|
itemCapacity = 120;
|
||||||
reloadTime = 200f;
|
reloadTime = 200f;
|
||||||
range = 440f;
|
range = 440f;
|
||||||
consumes.power(2f);
|
consumes.power(1.75f);
|
||||||
}};
|
}};
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
@@ -1299,8 +1290,8 @@ public class Blocks implements ContentList{
|
|||||||
Items.scrap, Bullets.flakScrap,
|
Items.scrap, Bullets.flakScrap,
|
||||||
Items.lead, Bullets.flakLead
|
Items.lead, Bullets.flakLead
|
||||||
);
|
);
|
||||||
reload = 15f;
|
reload = 16f;
|
||||||
range = 180f;
|
range = 175f;
|
||||||
size = 2;
|
size = 2;
|
||||||
burstSpacing = 5f;
|
burstSpacing = 5f;
|
||||||
shots = 2;
|
shots = 2;
|
||||||
@@ -1499,7 +1490,7 @@ public class Blocks implements ContentList{
|
|||||||
ammo(Items.graphite, Bullets.fuseShot);
|
ammo(Items.graphite, Bullets.fuseShot);
|
||||||
reload = 40f;
|
reload = 40f;
|
||||||
shootShake = 4f;
|
shootShake = 4f;
|
||||||
range = 80f;
|
range = 110f;
|
||||||
recoil = 5f;
|
recoil = 5f;
|
||||||
restitution = 0.1f;
|
restitution = 0.1f;
|
||||||
size = 3;
|
size = 3;
|
||||||
@@ -1544,7 +1535,7 @@ public class Blocks implements ContentList{
|
|||||||
reload = 50f;
|
reload = 50f;
|
||||||
firingMoveFract = 0.5f;
|
firingMoveFract = 0.5f;
|
||||||
shootDuration = 220f;
|
shootDuration = 220f;
|
||||||
powerUse = 10f;
|
powerUse = 14f;
|
||||||
|
|
||||||
health = 200 * size * size;
|
health = 200 * size * size;
|
||||||
consumes.add(new ConsumeLiquidFilter(liquid -> liquid.temperature <= 0.5f && liquid.flammability < 0.1f, 0.5f)).update(false);
|
consumes.add(new ConsumeLiquidFilter(liquid -> liquid.temperature <= 0.5f && liquid.flammability < 0.1f, 0.5f)).update(false);
|
||||||
|
|||||||
@@ -579,11 +579,12 @@ public class Bullets implements ContentList{
|
|||||||
|
|
||||||
fuseShot = new BulletType(0.01f, 70){
|
fuseShot = new BulletType(0.01f, 70){
|
||||||
int rays = 3;
|
int rays = 3;
|
||||||
float rayLength = 80f;
|
float rayLength = 120f;
|
||||||
|
|
||||||
{
|
{
|
||||||
hitEffect = Fx.hitFuse;
|
hitEffect = Fx.hitFuse;
|
||||||
lifetime = 13f;
|
shootEffect = smokeEffect = Fx.none;
|
||||||
|
lifetime = 10f;
|
||||||
despawnEffect = Fx.none;
|
despawnEffect = Fx.none;
|
||||||
pierce = true;
|
pierce = true;
|
||||||
}
|
}
|
||||||
@@ -599,14 +600,15 @@ public class Bullets implements ContentList{
|
|||||||
public void draw(Bullet b){
|
public void draw(Bullet b){
|
||||||
super.draw(b);
|
super.draw(b);
|
||||||
Draw.color(Color.WHITE, Pal.surge, b.fin());
|
Draw.color(Color.WHITE, Pal.surge, b.fin());
|
||||||
|
//Draw.alpha(b.fout());
|
||||||
for(int i = 0; i < 7; i++){
|
for(int i = 0; i < 7; i++){
|
||||||
Tmp.v1.trns(b.rot(), i * 8f);
|
Tmp.v1.trns(b.rot(), i * 8f);
|
||||||
float sl = Mathf.clamp(b.fout() - 0.5f) * (80f - i * 10);
|
float sl = Mathf.clamp(b.fout() - 0.5f) * (80f - i * 10);
|
||||||
Shapes.tri(b.x + Tmp.v1.x, b.y + Tmp.v1.y, 4f, sl, b.rot() + 90);
|
Shapes.tri(b.x + Tmp.v1.x, b.y + Tmp.v1.y, 4f, sl, b.rot() + 90);
|
||||||
Shapes.tri(b.x + Tmp.v1.x, b.y + Tmp.v1.y, 4f, sl, b.rot() - 90);
|
Shapes.tri(b.x + Tmp.v1.x, b.y + Tmp.v1.y, 4f, sl, b.rot() - 90);
|
||||||
}
|
}
|
||||||
Shapes.tri(b.x, b.y, 13f, (rayLength + 50) * b.fout(), b.rot());
|
Shapes.tri(b.x, b.y, 20f * b.fout(), (rayLength + 50), b.rot());
|
||||||
Shapes.tri(b.x, b.y, 13f, 10f * b.fout(), b.rot() + 180f);
|
Shapes.tri(b.x, b.y, 20f * b.fout(), 10f, b.rot() + 180f);
|
||||||
Draw.reset();
|
Draw.reset();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ public class Mechs implements ContentList{
|
|||||||
boostSpeed = 0.95f;
|
boostSpeed = 0.95f;
|
||||||
buildPower = 1.2f;
|
buildPower = 1.2f;
|
||||||
engineColor = Color.valueOf("ffd37f");
|
engineColor = Color.valueOf("ffd37f");
|
||||||
health = 300f;
|
health = 250f;
|
||||||
|
|
||||||
weapon = new Weapon("blaster"){{
|
weapon = new Weapon("blaster"){{
|
||||||
length = 1.5f;
|
length = 1.5f;
|
||||||
@@ -51,10 +51,6 @@ public class Mechs implements ContentList{
|
|||||||
player.healBy(Time.delta() * 0.09f);
|
player.healBy(Time.delta() * 0.09f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean alwaysUnlocked(){
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
delta = new Mech("delta-mech", false){
|
delta = new Mech("delta-mech", false){
|
||||||
@@ -66,7 +62,7 @@ public class Mechs implements ContentList{
|
|||||||
boostSpeed = 0.95f;
|
boostSpeed = 0.95f;
|
||||||
itemCapacity = 15;
|
itemCapacity = 15;
|
||||||
mass = 0.9f;
|
mass = 0.9f;
|
||||||
health = 250f;
|
health = 150f;
|
||||||
buildPower = 0.9f;
|
buildPower = 0.9f;
|
||||||
weaponOffsetX = -1;
|
weaponOffsetX = -1;
|
||||||
weaponOffsetY = -1;
|
weaponOffsetY = -1;
|
||||||
@@ -75,7 +71,7 @@ public class Mechs implements ContentList{
|
|||||||
weapon = new Weapon("shockgun"){{
|
weapon = new Weapon("shockgun"){{
|
||||||
shake = 2f;
|
shake = 2f;
|
||||||
length = 1f;
|
length = 1f;
|
||||||
reload = 40f;
|
reload = 45f;
|
||||||
shotDelay = 3f;
|
shotDelay = 3f;
|
||||||
roundrobin = true;
|
roundrobin = true;
|
||||||
shots = 2;
|
shots = 2;
|
||||||
@@ -163,12 +159,12 @@ public class Mechs implements ContentList{
|
|||||||
weaponOffsetX = 1;
|
weaponOffsetX = 1;
|
||||||
weaponOffsetY = 0;
|
weaponOffsetY = 0;
|
||||||
engineColor = Color.valueOf("feb380");
|
engineColor = Color.valueOf("feb380");
|
||||||
health = 300f;
|
health = 320f;
|
||||||
buildPower = 1.5f;
|
buildPower = 1.5f;
|
||||||
weapon = new Weapon("swarmer"){{
|
weapon = new Weapon("swarmer"){{
|
||||||
length = 1.5f;
|
length = 1.5f;
|
||||||
recoil = 4f;
|
recoil = 4f;
|
||||||
reload = 60f;
|
reload = 45f;
|
||||||
shots = 4;
|
shots = 4;
|
||||||
spacing = 8f;
|
spacing = 8f;
|
||||||
inaccuracy = 8f;
|
inaccuracy = 8f;
|
||||||
@@ -240,6 +236,11 @@ public class Mechs implements ContentList{
|
|||||||
bullet = Bullets.standardCopper;
|
bullet = Bullets.standardCopper;
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean alwaysUnlocked(){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
javelin = new Mech("javelin-ship", true){
|
javelin = new Mech("javelin-ship", true){
|
||||||
@@ -316,7 +317,7 @@ public class Mechs implements ContentList{
|
|||||||
itemCapacity = 30;
|
itemCapacity = 30;
|
||||||
engineColor = Color.valueOf("84f491");
|
engineColor = Color.valueOf("84f491");
|
||||||
cellTrnsY = 1f;
|
cellTrnsY = 1f;
|
||||||
buildPower = 2f;
|
buildPower = 2.5f;
|
||||||
weapon = new Weapon("bomber"){{
|
weapon = new Weapon("bomber"){{
|
||||||
length = 0f;
|
length = 0f;
|
||||||
width = 2f;
|
width = 2f;
|
||||||
@@ -329,7 +330,7 @@ public class Mechs implements ContentList{
|
|||||||
velocityRnd = 1f;
|
velocityRnd = 1f;
|
||||||
inaccuracy = 20f;
|
inaccuracy = 20f;
|
||||||
ignoreRotation = true;
|
ignoreRotation = true;
|
||||||
bullet = new BombBulletType(14f, 25f, "shell"){{
|
bullet = new BombBulletType(16f, 25f, "shell"){{
|
||||||
bulletWidth = 10f;
|
bulletWidth = 10f;
|
||||||
bulletHeight = 14f;
|
bulletHeight = 14f;
|
||||||
hitEffect = Fx.flakExplosion;
|
hitEffect = Fx.flakExplosion;
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ public class Control implements ApplicationListener{
|
|||||||
Net.host(port);
|
Net.host(port);
|
||||||
player.isAdmin = true;
|
player.isAdmin = true;
|
||||||
}catch(IOException e){
|
}catch(IOException e){
|
||||||
ui.showError(Core.bundle.format("server.error", Strings.parseException(e, false)));
|
ui.showError(Core.bundle.format("server.error", Strings.parseException(e, true)));
|
||||||
Core.app.post(() -> state.set(State.menu));
|
Core.app.post(() -> state.set(State.menu));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -234,7 +234,7 @@ public class NetServer implements ApplicationListener{
|
|||||||
}
|
}
|
||||||
player.remove();
|
player.remove();
|
||||||
netServer.connections.remove(player.con.id);
|
netServer.connections.remove(player.con.id);
|
||||||
Log.info("&lc{0} has disconnected.", player.name);
|
Log.info("&lm[{1}] &lc{0} has disconnected.", player.name, player.uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static float compound(float speed, float drag){
|
private static float compound(float speed, float drag){
|
||||||
@@ -248,16 +248,16 @@ public class NetServer implements ApplicationListener{
|
|||||||
|
|
||||||
@Remote(targets = Loc.client, unreliable = true)
|
@Remote(targets = Loc.client, unreliable = true)
|
||||||
public static void onClientShapshot(
|
public static void onClientShapshot(
|
||||||
Player player,
|
Player player,
|
||||||
int snapshotID,
|
int snapshotID,
|
||||||
float x, float y,
|
float x, float y,
|
||||||
float pointerX, float pointerY,
|
float pointerX, float pointerY,
|
||||||
float rotation, float baseRotation,
|
float rotation, float baseRotation,
|
||||||
float xVelocity, float yVelocity,
|
float xVelocity, float yVelocity,
|
||||||
Tile mining,
|
Tile mining,
|
||||||
boolean boosting, boolean shooting, boolean chatting,
|
boolean boosting, boolean shooting, boolean chatting,
|
||||||
BuildRequest[] requests,
|
BuildRequest[] requests,
|
||||||
float viewX, float viewY, float viewWidth, float viewHeight
|
float viewX, float viewY, float viewWidth, float viewHeight
|
||||||
){
|
){
|
||||||
NetConnection connection = player.con;
|
NetConnection connection = player.con;
|
||||||
if(connection == null || snapshotID < connection.lastRecievedClientSnapshot) return;
|
if(connection == null || snapshotID < connection.lastRecievedClientSnapshot) return;
|
||||||
@@ -296,7 +296,7 @@ public class NetServer implements ApplicationListener{
|
|||||||
}
|
}
|
||||||
|
|
||||||
vector.set(x - player.getInterpolator().target.x, y - player.getInterpolator().target.y);
|
vector.set(x - player.getInterpolator().target.x, y - player.getInterpolator().target.y);
|
||||||
vector.limit(maxMove);
|
//vector.limit(maxMove);
|
||||||
|
|
||||||
float prevx = player.x, prevy = player.y;
|
float prevx = player.x, prevy = player.y;
|
||||||
player.set(player.getInterpolator().target.x, player.getInterpolator().target.y);
|
player.set(player.getInterpolator().target.x, player.getInterpolator().target.y);
|
||||||
@@ -372,7 +372,7 @@ public class NetServer implements ApplicationListener{
|
|||||||
player.add();
|
player.add();
|
||||||
player.con.hasConnected = true;
|
player.con.hasConnected = true;
|
||||||
Call.sendMessage("[accent]" + player.name + "[accent] has connected.");
|
Call.sendMessage("[accent]" + player.name + "[accent] has connected.");
|
||||||
Log.info("&y{0} has connected.", player.name);
|
Log.info("&lm[{1}] &y{0} has connected. ", player.name, player.uuid);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isWaitingForPlayers(){
|
public boolean isWaitingForPlayers(){
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import io.anuke.arc.Core;
|
|||||||
import io.anuke.arc.Input.TextInput;
|
import io.anuke.arc.Input.TextInput;
|
||||||
import io.anuke.arc.files.FileHandle;
|
import io.anuke.arc.files.FileHandle;
|
||||||
import io.anuke.arc.function.Consumer;
|
import io.anuke.arc.function.Consumer;
|
||||||
|
import io.anuke.arc.function.Predicate;
|
||||||
import io.anuke.arc.math.RandomXS128;
|
import io.anuke.arc.math.RandomXS128;
|
||||||
import io.anuke.arc.scene.ui.TextField;
|
import io.anuke.arc.scene.ui.TextField;
|
||||||
import io.anuke.arc.util.serialization.Base64Coder;
|
import io.anuke.arc.util.serialization.Base64Coder;
|
||||||
@@ -66,14 +67,14 @@ public abstract class Platform{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Show a file chooser. Desktop only.
|
* Show a file chooser.
|
||||||
* @param text File chooser title text
|
* @param text File chooser title text
|
||||||
* @param content Description of the type of files to be loaded
|
* @param content Description of the type of files to be loaded
|
||||||
* @param cons Selection listener
|
* @param cons Selection listener
|
||||||
* @param open Whether to open or save files
|
* @param open Whether to open or save files
|
||||||
* @param filetype File extension to filter
|
* @param filetype File extension to filter
|
||||||
*/
|
*/
|
||||||
public void showFileChooser(String text, String content, Consumer<FileHandle> cons, boolean open, String filetype){
|
public void showFileChooser(String text, String content, Consumer<FileHandle> cons, boolean open, Predicate<String> filetype){
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Hide the app. Android only. */
|
/** Hide the app. Android only. */
|
||||||
|
|||||||
@@ -25,8 +25,7 @@ import io.anuke.mindustry.ui.dialogs.*;
|
|||||||
import io.anuke.mindustry.ui.fragments.*;
|
import io.anuke.mindustry.ui.fragments.*;
|
||||||
|
|
||||||
import static io.anuke.arc.scene.actions.Actions.*;
|
import static io.anuke.arc.scene.actions.Actions.*;
|
||||||
import static io.anuke.mindustry.Vars.control;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
import static io.anuke.mindustry.Vars.disableUI;
|
|
||||||
|
|
||||||
public class UI implements ApplicationListener{
|
public class UI implements ApplicationListener{
|
||||||
private FreeTypeFontGenerator generator;
|
private FreeTypeFontGenerator generator;
|
||||||
@@ -244,8 +243,17 @@ public class UI implements ApplicationListener{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void showError(String text){
|
public void showError(String text){
|
||||||
new Dialog("$error.title", "dialog"){{
|
new Dialog("", "dialog"){{
|
||||||
cont.margin(15).add(text).width(400f).wrap().get().setAlignment(Align.center, Align.center);
|
setFillParent(true);
|
||||||
|
cont.add("$error.title");
|
||||||
|
cont.row();
|
||||||
|
cont.margin(15).pane(t -> {
|
||||||
|
Label l = t.add(text).pad(14f).get();
|
||||||
|
l.setAlignment(Align.center, Align.left);
|
||||||
|
if(mobile){
|
||||||
|
t.getCell(l).wrap().width(400f);
|
||||||
|
}
|
||||||
|
});
|
||||||
buttons.addButton("$ok", this::hide).size(90, 50).pad(4);
|
buttons.addButton("$ok", this::hide).size(90, 50).pad(4);
|
||||||
}}.show();
|
}}.show();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,8 +12,13 @@ import static io.anuke.mindustry.Vars.content;
|
|||||||
import static io.anuke.mindustry.Vars.world;
|
import static io.anuke.mindustry.Vars.world;
|
||||||
|
|
||||||
public class DrawOperation{
|
public class DrawOperation{
|
||||||
|
private MapEditor editor;
|
||||||
private LongArray array = new LongArray();
|
private LongArray array = new LongArray();
|
||||||
|
|
||||||
|
public DrawOperation(MapEditor editor) {
|
||||||
|
this.editor = editor;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isEmpty(){
|
public boolean isEmpty(){
|
||||||
return array.isEmpty();
|
return array.isEmpty();
|
||||||
}
|
}
|
||||||
@@ -22,23 +27,25 @@ public class DrawOperation{
|
|||||||
array.add(op);
|
array.add(op);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void undo(MapEditor editor){
|
public void undo(){
|
||||||
for(int i = array.size - 1; i >= 0; i--){
|
for(int i = array.size - 1; i >= 0; i--){
|
||||||
long l = array.get(i);
|
updateTile(i);
|
||||||
array.set(i, TileOp.get(TileOp.x(l), TileOp.y(l), TileOp.type(l), get(editor.tile(TileOp.x(l), TileOp.y(l)), TileOp.type(l))));
|
|
||||||
set(editor, editor.tile(TileOp.x(l), TileOp.y(l)), TileOp.type(l), TileOp.value(l));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void redo(MapEditor editor){
|
public void redo(){
|
||||||
for(int i = 0; i < array.size; i++){
|
for(int i = 0; i < array.size; i++){
|
||||||
long l = array.get(i);
|
updateTile(i);
|
||||||
array.set(i, TileOp.get(TileOp.x(l), TileOp.y(l), TileOp.type(l), get(editor.tile(TileOp.x(l), TileOp.y(l)), TileOp.type(l))));
|
|
||||||
set(editor, editor.tile(TileOp.x(l), TileOp.y(l)), TileOp.type(l), TileOp.value(l));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
short get(Tile tile, byte type){
|
private void updateTile(int i) {
|
||||||
|
long l = array.get(i);
|
||||||
|
array.set(i, TileOp.get(TileOp.x(l), TileOp.y(l), TileOp.type(l), getTile(editor.tile(TileOp.x(l), TileOp.y(l)), TileOp.type(l))));
|
||||||
|
setTile(editor.tile(TileOp.x(l), TileOp.y(l)), TileOp.type(l), TileOp.value(l));
|
||||||
|
}
|
||||||
|
|
||||||
|
short getTile(Tile tile, byte type){
|
||||||
if(type == OpType.floor.ordinal()){
|
if(type == OpType.floor.ordinal()){
|
||||||
return tile.floorID();
|
return tile.floorID();
|
||||||
}else if(type == OpType.block.ordinal()){
|
}else if(type == OpType.block.ordinal()){
|
||||||
@@ -53,7 +60,7 @@ public class DrawOperation{
|
|||||||
throw new IllegalArgumentException("Invalid type.");
|
throw new IllegalArgumentException("Invalid type.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(MapEditor editor, Tile tile, byte type, short to){
|
void setTile(Tile tile, byte type, short to){
|
||||||
editor.load(() -> {
|
editor.load(() -> {
|
||||||
if(type == OpType.floor.ordinal()){
|
if(type == OpType.floor.ordinal()){
|
||||||
tile.setFloor((Floor)content.block(to));
|
tile.setFloor((Floor)content.block(to));
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ public class EditorTile extends Tile{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(overlayID() == overlay) return;
|
if(overlayID() == overlay) return;
|
||||||
op(OpType.overlay, overlay);
|
op(OpType.overlay, this.overlay);
|
||||||
super.setOverlayID(overlay);
|
super.setOverlayID(overlay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ public enum EditorTool{
|
|||||||
|
|
||||||
IntArray stack = new IntArray();
|
IntArray stack = new IntArray();
|
||||||
Block dest;
|
Block dest;
|
||||||
boolean isfloor;
|
boolean isFloor;
|
||||||
MapEditor data;
|
MapEditor data;
|
||||||
|
|
||||||
public void touched(MapEditor editor, int x, int y){
|
public void touched(MapEditor editor, int x, int y){
|
||||||
@@ -64,14 +64,14 @@ public enum EditorTool{
|
|||||||
}
|
}
|
||||||
|
|
||||||
data = editor;
|
data = editor;
|
||||||
isfloor = editor.drawBlock instanceof Floor;
|
isFloor = editor.drawBlock instanceof Floor;
|
||||||
|
|
||||||
Block floor = tile.floor();
|
Block floor = tile.floor();
|
||||||
Block block = tile.block();
|
Block block = tile.block();
|
||||||
boolean synth = editor.drawBlock.synthetic();
|
boolean synth = editor.drawBlock.synthetic();
|
||||||
|
|
||||||
Block draw = editor.drawBlock;
|
Block draw = editor.drawBlock;
|
||||||
dest = draw instanceof OverlayFloor ? tile.overlay() : isfloor ? floor : block;
|
dest = draw instanceof OverlayFloor ? tile.overlay() : isFloor ? floor : block;
|
||||||
|
|
||||||
if(dest == draw || block instanceof BlockPart || block.isMultiblock()){
|
if(dest == draw || block instanceof BlockPart || block.isMultiblock()){
|
||||||
return;
|
return;
|
||||||
@@ -85,7 +85,7 @@ public enum EditorTool{
|
|||||||
IntPositionConsumer writer = (px, py) -> {
|
IntPositionConsumer writer = (px, py) -> {
|
||||||
Tile write = editor.tile(px, py);
|
Tile write = editor.tile(px, py);
|
||||||
|
|
||||||
if(isfloor){
|
if(isFloor){
|
||||||
if(alt && !(draw instanceof OverlayFloor)){
|
if(alt && !(draw instanceof OverlayFloor)){
|
||||||
Block ore = write.overlay();
|
Block ore = write.overlay();
|
||||||
write.setFloor((Floor)draw);
|
write.setFloor((Floor)draw);
|
||||||
@@ -167,7 +167,7 @@ public enum EditorTool{
|
|||||||
boolean eq(int px, int py){
|
boolean eq(int px, int py){
|
||||||
Tile tile = data.tile(px, py);
|
Tile tile = data.tile(px, py);
|
||||||
|
|
||||||
return (data.drawBlock instanceof OverlayFloor ? tile.overlay() : isfloor ? tile.floor() : tile.block()) == dest && !(data.drawBlock instanceof OverlayFloor && tile.floor().isLiquid);
|
return (data.drawBlock instanceof OverlayFloor ? tile.overlay() : isFloor ? tile.floor() : tile.block()) == dest && !(data.drawBlock instanceof OverlayFloor && tile.floor().isLiquid);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
spray{
|
spray{
|
||||||
|
|||||||
@@ -240,13 +240,13 @@ public class MapEditor{
|
|||||||
|
|
||||||
public void undo(){
|
public void undo(){
|
||||||
if(stack.canUndo()){
|
if(stack.canUndo()){
|
||||||
stack.undo(this);
|
stack.undo();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void redo(){
|
public void redo(){
|
||||||
if(stack.canRedo()){
|
if(stack.canRedo()){
|
||||||
stack.redo(this);
|
stack.redo();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -267,7 +267,7 @@ public class MapEditor{
|
|||||||
public void addTileOp(long data){
|
public void addTileOp(long data){
|
||||||
if(loading) return;
|
if(loading) return;
|
||||||
|
|
||||||
if(currentOp == null) currentOp = new DrawOperation();
|
if(currentOp == null) currentOp = new DrawOperation(this);
|
||||||
currentOp.addOperation(data);
|
currentOp.addOperation(data);
|
||||||
|
|
||||||
renderer.updatePoint(TileOp.x(data), TileOp.y(data));
|
renderer.updatePoint(TileOp.x(data), TileOp.y(data));
|
||||||
|
|||||||
@@ -21,9 +21,9 @@ import io.anuke.mindustry.Vars;
|
|||||||
import io.anuke.mindustry.core.GameState.State;
|
import io.anuke.mindustry.core.GameState.State;
|
||||||
import io.anuke.mindustry.core.Platform;
|
import io.anuke.mindustry.core.Platform;
|
||||||
import io.anuke.mindustry.game.*;
|
import io.anuke.mindustry.game.*;
|
||||||
import io.anuke.mindustry.io.JsonIO;
|
import io.anuke.mindustry.io.*;
|
||||||
import io.anuke.mindustry.io.MapIO;
|
|
||||||
import io.anuke.mindustry.maps.Map;
|
import io.anuke.mindustry.maps.Map;
|
||||||
|
import io.anuke.mindustry.ui.dialogs.FileChooser;
|
||||||
import io.anuke.mindustry.ui.dialogs.FloatingDialog;
|
import io.anuke.mindustry.ui.dialogs.FloatingDialog;
|
||||||
import io.anuke.mindustry.world.Block;
|
import io.anuke.mindustry.world.Block;
|
||||||
import io.anuke.mindustry.world.Block.Icon;
|
import io.anuke.mindustry.world.Block.Icon;
|
||||||
@@ -93,14 +93,16 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
|||||||
"$editor.importmap", "$editor.importmap.description", "icon-load-map", (Runnable)loadDialog::show,
|
"$editor.importmap", "$editor.importmap.description", "icon-load-map", (Runnable)loadDialog::show,
|
||||||
"$editor.importfile", "$editor.importfile.description", "icon-file", (Runnable)() ->
|
"$editor.importfile", "$editor.importfile.description", "icon-file", (Runnable)() ->
|
||||||
Platform.instance.showFileChooser("$editor.loadmap", "Map Files", file -> ui.loadAnd(() -> {
|
Platform.instance.showFileChooser("$editor.loadmap", "Map Files", file -> ui.loadAnd(() -> {
|
||||||
try{
|
world.maps.tryCatchMapError(() -> {
|
||||||
//TODO what if it's an image? users should be warned for their stupidity
|
if(MapIO.isImage(file)){
|
||||||
editor.beginEdit(MapIO.createMap(file, true));
|
ui.showInfo("$editor.errorimage");
|
||||||
}catch(Exception e){
|
}else if(file.extension().equalsIgnoreCase(oldMapExtension)){
|
||||||
ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, false)));
|
editor.beginEdit(world.maps.makeLegacyMap(file));
|
||||||
Log.err(e);
|
}else{
|
||||||
}
|
editor.beginEdit(MapIO.createMap(file, true));
|
||||||
}), true, mapExtension),
|
}
|
||||||
|
});
|
||||||
|
}), true, FileChooser.anyMapFiles),
|
||||||
|
|
||||||
"$editor.importimage", "$editor.importimage.description", "icon-file-image", (Runnable)() ->
|
"$editor.importimage", "$editor.importimage.description", "icon-file-image", (Runnable)() ->
|
||||||
Platform.instance.showFileChooser("$loadimage", "Image Files", file ->
|
Platform.instance.showFileChooser("$loadimage", "Image Files", file ->
|
||||||
@@ -110,10 +112,10 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
|||||||
editor.beginEdit(pixmap);
|
editor.beginEdit(pixmap);
|
||||||
pixmap.dispose();
|
pixmap.dispose();
|
||||||
}catch(Exception e){
|
}catch(Exception e){
|
||||||
ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, false)));
|
ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, true)));
|
||||||
Log.err(e);
|
Log.err(e);
|
||||||
}
|
}
|
||||||
}), true, "png"))
|
}), true, FileChooser.pngFiles))
|
||||||
);
|
);
|
||||||
|
|
||||||
t.addImageTextButton("$editor.export", "icon-save-map", isize, () ->
|
t.addImageTextButton("$editor.export", "icon-save-map", isize, () ->
|
||||||
@@ -127,11 +129,11 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
|||||||
}
|
}
|
||||||
MapIO.writeMap(result, editor.createMap(result));
|
MapIO.writeMap(result, editor.createMap(result));
|
||||||
}catch(Exception e){
|
}catch(Exception e){
|
||||||
ui.showError(Core.bundle.format("editor.errorsave", Strings.parseException(e, false)));
|
ui.showError(Core.bundle.format("editor.errorsave", Strings.parseException(e, true)));
|
||||||
Log.err(e);
|
Log.err(e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}, false, mapExtension));
|
}, false, FileChooser.mapFiles));
|
||||||
});
|
});
|
||||||
|
|
||||||
menu.cont.row();
|
menu.cont.row();
|
||||||
@@ -153,12 +155,11 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
loadDialog = new MapLoadDialog(map ->
|
loadDialog = new MapLoadDialog(map -> ui.loadAnd(() -> {
|
||||||
ui.loadAnd(() -> {
|
|
||||||
try{
|
try{
|
||||||
editor.beginEdit(map);
|
editor.beginEdit(map);
|
||||||
}catch(Exception e){
|
}catch(Exception e){
|
||||||
ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, false)));
|
ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, true)));
|
||||||
Log.err(e);
|
Log.err(e);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
@@ -188,13 +189,14 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
|||||||
});
|
});
|
||||||
|
|
||||||
shown(() -> {
|
shown(() -> {
|
||||||
//clear units, rules and other unnecessary stuff
|
|
||||||
logic.reset();
|
|
||||||
saved = true;
|
saved = true;
|
||||||
if(!Core.settings.getBool("landscape")) Platform.instance.beginForceLandscape();
|
if(!Core.settings.getBool("landscape")) Platform.instance.beginForceLandscape();
|
||||||
editor.clearOp();
|
editor.clearOp();
|
||||||
Core.scene.setScrollFocus(view);
|
Core.scene.setScrollFocus(view);
|
||||||
if(!shownWithMap){
|
if(!shownWithMap){
|
||||||
|
//clear units, rules and other unnecessary stuff
|
||||||
|
logic.reset();
|
||||||
state.rules = new Rules();
|
state.rules = new Rules();
|
||||||
editor.beginEdit(200, 200);
|
editor.beginEdit(200, 200);
|
||||||
}
|
}
|
||||||
@@ -231,7 +233,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
|||||||
hide();
|
hide();
|
||||||
//only reset the player; logic.reset() will clear entities, which we do not want
|
//only reset the player; logic.reset() will clear entities, which we do not want
|
||||||
player.reset();
|
player.reset();
|
||||||
state.rules = Gamemode.editor.apply(new Rules());
|
state.rules = Gamemode.editor.apply(lastSavedRules.copy());
|
||||||
world.setMap(new Map(StringMap.of(
|
world.setMap(new Map(StringMap.of(
|
||||||
"name", "Editor Playtesting",
|
"name", "Editor Playtesting",
|
||||||
"width", editor.width(),
|
"width", editor.width(),
|
||||||
@@ -256,6 +258,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
|||||||
private void save(){
|
private void save(){
|
||||||
String name = editor.getTags().get("name", "").trim();
|
String name = editor.getTags().get("name", "").trim();
|
||||||
editor.getTags().put("rules", JsonIO.write(state.rules));
|
editor.getTags().put("rules", JsonIO.write(state.rules));
|
||||||
|
player.dead = true;
|
||||||
|
|
||||||
if(name.isEmpty()){
|
if(name.isEmpty()){
|
||||||
infoDialog.show();
|
infoDialog.show();
|
||||||
@@ -335,7 +338,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
|||||||
show();
|
show();
|
||||||
}catch(Exception e){
|
}catch(Exception e){
|
||||||
Log.err(e);
|
Log.err(e);
|
||||||
ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, false)));
|
ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, true)));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,21 +27,22 @@ import static io.anuke.mindustry.Vars.*;
|
|||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public class MapGenerateDialog extends FloatingDialog{
|
public class MapGenerateDialog extends FloatingDialog{
|
||||||
|
private final Supplier<GenerateFilter>[] filterTypes = new Supplier[]{NoiseFilter::new, ScatterFilter::new, TerrainFilter::new, DistortFilter::new, RiverNoiseFilter::new, OreFilter::new, MedianFilter::new};
|
||||||
private final MapEditor editor;
|
private final MapEditor editor;
|
||||||
|
|
||||||
private Pixmap pixmap;
|
private Pixmap pixmap;
|
||||||
private Texture texture;
|
private Texture texture;
|
||||||
private GenerateInput input = new GenerateInput();
|
private GenerateInput input = new GenerateInput();
|
||||||
private Array<GenerateFilter> filters = new Array<>();
|
private Array<GenerateFilter> filters = new Array<>();
|
||||||
private int scaling = mobile ? 3 : 1;
|
private int scaling = mobile ? 3 : 1;
|
||||||
private Supplier<GenerateFilter>[] filterTypes = new Supplier[]{NoiseFilter::new, ScatterFilter::new, TerrainFilter::new, DistortFilter::new, RiverNoiseFilter::new, OreFilter::new};
|
|
||||||
private Table filterTable;
|
private Table filterTable;
|
||||||
|
|
||||||
private AsyncExecutor executor = new AsyncExecutor(1);
|
private AsyncExecutor executor = new AsyncExecutor(1);
|
||||||
private AsyncResult<Void> result;
|
private AsyncResult<Void> result;
|
||||||
private boolean generating;
|
private boolean generating;
|
||||||
private DummyTile returnTile = new DummyTile();
|
private GenTile returnTile = new GenTile();
|
||||||
|
|
||||||
private DummyTile[][] buffer1, buffer2;
|
private GenTile[][] buffer1, buffer2;
|
||||||
|
|
||||||
public MapGenerateDialog(MapEditor editor){
|
public MapGenerateDialog(MapEditor editor){
|
||||||
super("$editor.generate");
|
super("$editor.generate");
|
||||||
@@ -98,12 +99,12 @@ public class MapGenerateDialog extends FloatingDialog{
|
|||||||
rebuildFilters();
|
rebuildFilters();
|
||||||
}
|
}
|
||||||
|
|
||||||
DummyTile[][] create(){
|
GenTile[][] create(){
|
||||||
DummyTile[][] out = new DummyTile[editor.width() / scaling][editor.height() / scaling];
|
GenTile[][] out = new GenTile[editor.width() / scaling][editor.height() / scaling];
|
||||||
|
|
||||||
for(int x = 0; x < out.length; x++){
|
for(int x = 0; x < out.length; x++){
|
||||||
for(int y = 0; y < out[0].length; y++){
|
for(int y = 0; y < out[0].length; y++){
|
||||||
out[x][y] = new DummyTile();
|
out[x][y] = new GenTile();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
@@ -187,7 +188,7 @@ public class MapGenerateDialog extends FloatingDialog{
|
|||||||
selection.show();
|
selection.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
DummyTile dset(Tile tile){
|
GenTile dset(Tile tile){
|
||||||
returnTile.set(tile);
|
returnTile.set(tile);
|
||||||
return returnTile;
|
return returnTile;
|
||||||
}
|
}
|
||||||
@@ -208,11 +209,11 @@ public class MapGenerateDialog extends FloatingDialog{
|
|||||||
}
|
}
|
||||||
|
|
||||||
//writeback buffer
|
//writeback buffer
|
||||||
DummyTile[][] writeTiles = new DummyTile[editor.width()][editor.height()];
|
GenTile[][] writeTiles = new GenTile[editor.width()][editor.height()];
|
||||||
|
|
||||||
for(int x = 0; x < editor.width(); x++){
|
for(int x = 0; x < editor.width(); x++){
|
||||||
for(int y = 0; y < editor.height(); y++){
|
for(int y = 0; y < editor.height(); y++){
|
||||||
writeTiles[x][y] = new DummyTile();
|
writeTiles[x][y] = new GenTile();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -233,7 +234,7 @@ public class MapGenerateDialog extends FloatingDialog{
|
|||||||
for(int x = 0; x < editor.width(); x++){
|
for(int x = 0; x < editor.width(); x++){
|
||||||
for(int y = 0; y < editor.height(); y++){
|
for(int y = 0; y < editor.height(); y++){
|
||||||
Tile tile = editor.tile(x, y);
|
Tile tile = editor.tile(x, y);
|
||||||
DummyTile write = writeTiles[x][y];
|
GenTile write = writeTiles[x][y];
|
||||||
|
|
||||||
tile.rotation(write.rotation);
|
tile.rotation(write.rotation);
|
||||||
tile.setFloor((Floor)content.block(write.floor));
|
tile.setFloor((Floor)content.block(write.floor));
|
||||||
@@ -278,7 +279,7 @@ public class MapGenerateDialog extends FloatingDialog{
|
|||||||
for(int px = 0; px < pixmap.getWidth(); px++){
|
for(int px = 0; px < pixmap.getWidth(); px++){
|
||||||
for(int py = 0; py < pixmap.getHeight(); py++){
|
for(int py = 0; py < pixmap.getHeight(); py++){
|
||||||
int x = px * scaling, y = py * scaling;
|
int x = px * scaling, y = py * scaling;
|
||||||
DummyTile tile = buffer1[px][py];
|
GenTile tile = buffer1[px][py];
|
||||||
input.begin(editor, x, y, content.block(tile.floor), content.block(tile.block), content.block(tile.ore));
|
input.begin(editor, x, y, content.block(tile.floor), content.block(tile.block), content.block(tile.ore));
|
||||||
filter.apply(input);
|
filter.apply(input);
|
||||||
buffer2[px][py].set(input.floor, input.block, input.ore, Team.all[tile.team], tile.rotation);
|
buffer2[px][py].set(input.floor, input.block, input.ore, Team.all[tile.team], tile.rotation);
|
||||||
@@ -299,7 +300,7 @@ public class MapGenerateDialog extends FloatingDialog{
|
|||||||
Tile tile = editor.tile(px * scaling, py * scaling);
|
Tile tile = editor.tile(px * scaling, py * scaling);
|
||||||
color = MapIO.colorFor(tile.floor(), tile.block(), tile.overlay(), Team.none);
|
color = MapIO.colorFor(tile.floor(), tile.block(), tile.overlay(), Team.none);
|
||||||
}else{
|
}else{
|
||||||
DummyTile tile = buffer1[px][py];
|
GenTile tile = buffer1[px][py];
|
||||||
color = MapIO.colorFor(content.block(tile.floor), content.block(tile.block), content.block(tile.ore), Team.none);
|
color = MapIO.colorFor(content.block(tile.floor), content.block(tile.block), content.block(tile.ore), Team.none);
|
||||||
}
|
}
|
||||||
pixmap.drawPixel(px, pixmap.getHeight() - 1 - py, color);
|
pixmap.drawPixel(px, pixmap.getHeight() - 1 - py, color);
|
||||||
@@ -321,7 +322,7 @@ public class MapGenerateDialog extends FloatingDialog{
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class DummyTile{
|
public static class GenTile{
|
||||||
public byte team, rotation;
|
public byte team, rotation;
|
||||||
public short block, floor, ore;
|
public short block, floor, ore;
|
||||||
|
|
||||||
@@ -333,7 +334,7 @@ public class MapGenerateDialog extends FloatingDialog{
|
|||||||
this.rotation = (byte)rotation;
|
this.rotation = (byte)rotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
void set(DummyTile other){
|
void set(GenTile other){
|
||||||
this.floor = other.floor;
|
this.floor = other.floor;
|
||||||
this.block = other.block;
|
this.block = other.block;
|
||||||
this.ore = other.ore;
|
this.ore = other.ore;
|
||||||
|
|||||||
@@ -12,13 +12,13 @@ import io.anuke.mindustry.ui.dialogs.FloatingDialog;
|
|||||||
|
|
||||||
public class MapInfoDialog extends FloatingDialog{
|
public class MapInfoDialog extends FloatingDialog{
|
||||||
private final MapEditor editor;
|
private final MapEditor editor;
|
||||||
private final WaveInfoDialog waveinfo;
|
private final WaveInfoDialog waveInfo;
|
||||||
private final CustomRulesDialog ruleinfo = new CustomRulesDialog();
|
private final CustomRulesDialog ruleInfo = new CustomRulesDialog();
|
||||||
|
|
||||||
public MapInfoDialog(MapEditor editor){
|
public MapInfoDialog(MapEditor editor){
|
||||||
super("$editor.mapinfo");
|
super("$editor.mapinfo");
|
||||||
this.editor = editor;
|
this.editor = editor;
|
||||||
this.waveinfo = new WaveInfoDialog(editor);
|
this.waveInfo = new WaveInfoDialog(editor);
|
||||||
|
|
||||||
addCloseButton();
|
addCloseButton();
|
||||||
|
|
||||||
@@ -58,11 +58,11 @@ public class MapInfoDialog extends FloatingDialog{
|
|||||||
|
|
||||||
cont.row();
|
cont.row();
|
||||||
cont.add("$editor.rules").padRight(8).left();
|
cont.add("$editor.rules").padRight(8).left();
|
||||||
cont.addButton("$edit", () -> ruleinfo.show(Vars.state.rules, () -> Vars.state.rules = new Rules())).left().width(200f);;
|
cont.addButton("$edit", () -> ruleInfo.show(Vars.state.rules, () -> Vars.state.rules = new Rules())).left().width(200f);;
|
||||||
|
|
||||||
cont.row();
|
cont.row();
|
||||||
cont.add("$editor.waves").padRight(8).left();
|
cont.add("$editor.waves").padRight(8).left();
|
||||||
cont.addButton("$edit", waveinfo::show).left().width(200f);
|
cont.addButton("$edit", waveInfo::show).left().width(200f);
|
||||||
|
|
||||||
name.change();
|
name.change();
|
||||||
description.change();
|
description.change();
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import io.anuke.mindustry.world.blocks.BlockPart;
|
|||||||
import static io.anuke.mindustry.Vars.tilesize;
|
import static io.anuke.mindustry.Vars.tilesize;
|
||||||
|
|
||||||
public class MapRenderer implements Disposable{
|
public class MapRenderer implements Disposable{
|
||||||
private static final int chunksize = 64;
|
private static final int chunkSize = 64;
|
||||||
private IndexedRenderer[][] chunks;
|
private IndexedRenderer[][] chunks;
|
||||||
private IntSet updates = new IntSet();
|
private IntSet updates = new IntSet();
|
||||||
private IntSet delayedUpdates = new IntSet();
|
private IntSet delayedUpdates = new IntSet();
|
||||||
@@ -41,11 +41,11 @@ public class MapRenderer implements Disposable{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
chunks = new IndexedRenderer[(int)Math.ceil((float)width / chunksize)][(int)Math.ceil((float)height / chunksize)];
|
chunks = new IndexedRenderer[(int)Math.ceil((float)width / chunkSize)][(int)Math.ceil((float)height / chunkSize)];
|
||||||
|
|
||||||
for(int x = 0; x < chunks.length; x++){
|
for(int x = 0; x < chunks.length; x++){
|
||||||
for(int y = 0; y < chunks[0].length; y++){
|
for(int y = 0; y < chunks[0].length; y++){
|
||||||
chunks[x][y] = new IndexedRenderer(chunksize * chunksize * 2);
|
chunks[x][y] = new IndexedRenderer(chunkSize * chunkSize * 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.width = width;
|
this.width = width;
|
||||||
@@ -97,7 +97,7 @@ public class MapRenderer implements Disposable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void render(int wx, int wy){
|
private void render(int wx, int wy){
|
||||||
int x = wx / chunksize, y = wy / chunksize;
|
int x = wx / chunkSize, y = wy / chunkSize;
|
||||||
IndexedRenderer mesh = chunks[x][y];
|
IndexedRenderer mesh = chunks[x][y];
|
||||||
Tile tile = editor.tiles()[wx][wy];
|
Tile tile = editor.tiles()[wx][wy];
|
||||||
|
|
||||||
@@ -107,8 +107,8 @@ public class MapRenderer implements Disposable{
|
|||||||
|
|
||||||
TextureRegion region;
|
TextureRegion region;
|
||||||
|
|
||||||
int idxWall = (wx % chunksize) + (wy % chunksize) * chunksize;
|
int idxWall = (wx % chunkSize) + (wy % chunkSize) * chunkSize;
|
||||||
int idxDecal = (wx % chunksize) + (wy % chunksize) * chunksize + chunksize * chunksize;
|
int idxDecal = (wx % chunkSize) + (wy % chunkSize) * chunkSize + chunkSize * chunkSize;
|
||||||
|
|
||||||
if(wall != Blocks.air && (wall.synthetic() || wall instanceof BlockPart)){
|
if(wall != Blocks.air && (wall.synthetic() || wall instanceof BlockPart)){
|
||||||
region = !Core.atlas.isFound(wall.editorIcon()) ? Core.atlas.find("clear-editor") : wall.editorIcon();
|
region = !Core.atlas.isFound(wall.editorIcon()) ? Core.atlas.find("clear-editor") : wall.editorIcon();
|
||||||
@@ -145,8 +145,8 @@ public class MapRenderer implements Disposable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
mesh.draw(idxDecal, region,
|
mesh.draw(idxDecal, region,
|
||||||
wx * tilesize + offsetX, wy * tilesize + offsetY,
|
wx * tilesize + offsetX, wy * tilesize + offsetY,
|
||||||
region.getWidth() * Draw.scl, region.getHeight() * Draw.scl);
|
region.getWidth() * Draw.scl, region.getHeight() * Draw.scl);
|
||||||
mesh.setColor(Color.WHITE);
|
mesh.setColor(Color.WHITE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,18 +34,18 @@ public class OperationStack{
|
|||||||
return !(index > -1 || stack.size + index < 0);
|
return !(index > -1 || stack.size + index < 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void undo(MapEditor editor){
|
public void undo(){
|
||||||
if(!canUndo()) return;
|
if(!canUndo()) return;
|
||||||
|
|
||||||
stack.get(stack.size - 1 + index).undo(editor);
|
stack.get(stack.size - 1 + index).undo();
|
||||||
index--;
|
index--;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void redo(MapEditor editor){
|
public void redo(){
|
||||||
if(!canRedo()) return;
|
if(!canRedo()) return;
|
||||||
|
|
||||||
index++;
|
index++;
|
||||||
stack.get(stack.size - 1 + index).redo(editor);
|
stack.get(stack.size - 1 + index).redo();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package io.anuke.mindustry.editor.generation;
|
package io.anuke.mindustry.editor.generation;
|
||||||
|
|
||||||
import io.anuke.mindustry.editor.MapGenerateDialog.DummyTile;
|
import io.anuke.mindustry.editor.MapGenerateDialog.GenTile;
|
||||||
import io.anuke.mindustry.editor.generation.FilterOption.SliderOption;
|
import io.anuke.mindustry.editor.generation.FilterOption.SliderOption;
|
||||||
import io.anuke.mindustry.world.blocks.Floor;
|
import io.anuke.mindustry.world.blocks.Floor;
|
||||||
|
|
||||||
@@ -11,14 +11,14 @@ public class DistortFilter extends GenerateFilter{
|
|||||||
|
|
||||||
{
|
{
|
||||||
options(
|
options(
|
||||||
new SliderOption("scale", () -> scl, f -> scl = f, 1f, 400f),
|
new SliderOption("scale", () -> scl, f -> scl = f, 1f, 400f),
|
||||||
new SliderOption("mag", () -> mag, f -> mag = f, 0.5f, 100f)
|
new SliderOption("mag", () -> mag, f -> mag = f, 0.5f, 100f)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void apply(){
|
public void apply(){
|
||||||
DummyTile tile = in.tile(in.x / (in.scaling) + (noise(in.x, in.y, scl, mag) - mag / 2f) / in.scaling, in.y / (in.scaling) + (noise(in.x, in.y + o, scl, mag) - mag / 2f) / in.scaling);
|
GenTile tile = in.tile(in.x / (in.scaling) + (noise(in.x, in.y, scl, mag) - mag / 2f) / in.scaling, in.y / (in.scaling) + (noise(in.x, in.y + o, scl, mag) - mag / 2f) / in.scaling);
|
||||||
|
|
||||||
in.floor = content.block(tile.floor);
|
in.floor = content.block(tile.floor);
|
||||||
if(!content.block(tile.block).synthetic() && !in.block.synthetic()) in.block = content.block(tile.block);
|
if(!content.block(tile.block).synthetic() && !in.block.synthetic()) in.block = content.block(tile.block);
|
||||||
|
|||||||
@@ -7,14 +7,14 @@ import io.anuke.arc.util.noise.RidgedPerlin;
|
|||||||
import io.anuke.arc.util.noise.Simplex;
|
import io.anuke.arc.util.noise.Simplex;
|
||||||
import io.anuke.mindustry.content.Blocks;
|
import io.anuke.mindustry.content.Blocks;
|
||||||
import io.anuke.mindustry.editor.MapEditor;
|
import io.anuke.mindustry.editor.MapEditor;
|
||||||
import io.anuke.mindustry.editor.MapGenerateDialog.DummyTile;
|
import io.anuke.mindustry.editor.MapGenerateDialog.GenTile;
|
||||||
import io.anuke.mindustry.world.Block;
|
import io.anuke.mindustry.world.Block;
|
||||||
import io.anuke.mindustry.world.blocks.Floor;
|
import io.anuke.mindustry.world.blocks.Floor;
|
||||||
|
|
||||||
public abstract class GenerateFilter{
|
public abstract class GenerateFilter{
|
||||||
protected float o = (float)(Math.random() * 10000000.0);
|
protected transient float o = (float)(Math.random() * 10000000.0);
|
||||||
protected long seed;
|
protected transient long seed;
|
||||||
protected GenerateInput in;
|
protected transient GenerateInput in;
|
||||||
|
|
||||||
public FilterOption[] options;
|
public FilterOption[] options;
|
||||||
|
|
||||||
@@ -88,12 +88,12 @@ public abstract class GenerateFilter{
|
|||||||
pnoise.setSeed((int)(filter.seed + 1));
|
pnoise.setSeed((int)(filter.seed + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
DummyTile tile(float x, float y){
|
GenTile tile(float x, float y){
|
||||||
return buffer.get(Mathf.clamp((int)x, 0, width - 1), Mathf.clamp((int)y, 0, height - 1));
|
return buffer.get(Mathf.clamp((int)x, 0, width - 1), Mathf.clamp((int)y, 0, height - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface TileProvider{
|
public interface TileProvider{
|
||||||
DummyTile get(int x, int y);
|
GenTile get(int x, int y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package io.anuke.mindustry.editor.generation;
|
||||||
|
|
||||||
|
import io.anuke.arc.collection.IntArray;
|
||||||
|
import io.anuke.arc.math.Mathf;
|
||||||
|
import io.anuke.mindustry.editor.MapGenerateDialog.GenTile;
|
||||||
|
import io.anuke.mindustry.editor.generation.FilterOption.SliderOption;
|
||||||
|
|
||||||
|
import static io.anuke.mindustry.Vars.content;
|
||||||
|
|
||||||
|
public class MedianFilter extends GenerateFilter{
|
||||||
|
float radius = 2;
|
||||||
|
float percentile = 0.5f;
|
||||||
|
IntArray blocks = new IntArray(), floors = new IntArray();
|
||||||
|
|
||||||
|
{
|
||||||
|
options(
|
||||||
|
new SliderOption("radius", () -> radius, f -> radius = f, 1f, 12f),
|
||||||
|
new SliderOption("percentile", () -> percentile, f -> percentile = f, 0f, 1f)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void apply(){
|
||||||
|
int rad = (int)radius;
|
||||||
|
blocks.clear();
|
||||||
|
floors.clear();
|
||||||
|
for(int x = -rad; x <= rad; x++){
|
||||||
|
for(int y = -rad; y <= rad; y++){
|
||||||
|
if(Mathf.dst2(x, y) > rad*rad) continue;
|
||||||
|
|
||||||
|
GenTile tile = in.tile(in.x + x, in.y + y);
|
||||||
|
blocks.add(tile.block);
|
||||||
|
floors.add(tile.floor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
floors.sort();
|
||||||
|
blocks.sort();
|
||||||
|
|
||||||
|
int index = Math.min((int)(floors.size * percentile), floors.size - 1);
|
||||||
|
int floor = floors.get(index), block = blocks.get(index);
|
||||||
|
|
||||||
|
in.floor = content.block(floor);
|
||||||
|
if(!content.block(block).synthetic() && !in.block.synthetic()) in.block = content.block(block);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -28,6 +28,7 @@ public class LiquidBulletType extends BulletType{
|
|||||||
statusDuration = 90f;
|
statusDuration = 90f;
|
||||||
despawnEffect = Fx.none;
|
despawnEffect = Fx.none;
|
||||||
hitEffect = Fx.hitLiquid;
|
hitEffect = Fx.hitLiquid;
|
||||||
|
smokeEffect = Fx.none;
|
||||||
shootEffect = Fx.none;
|
shootEffect = Fx.none;
|
||||||
drag = 0.009f;
|
drag = 0.009f;
|
||||||
knockback = 0.55f;
|
knockback = 0.55f;
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package io.anuke.mindustry.entities.effect;
|
package io.anuke.mindustry.entities.effect;
|
||||||
|
|
||||||
import io.anuke.arc.graphics.Color;
|
|
||||||
import io.anuke.arc.graphics.g2d.Draw;
|
import io.anuke.arc.graphics.g2d.Draw;
|
||||||
import io.anuke.arc.math.Mathf;
|
import io.anuke.arc.math.Mathf;
|
||||||
import io.anuke.mindustry.entities.EntityGroup;
|
import io.anuke.mindustry.entities.EntityGroup;
|
||||||
import io.anuke.mindustry.entities.impl.TimedEntity;
|
import io.anuke.mindustry.entities.impl.TimedEntity;
|
||||||
import io.anuke.mindustry.entities.traits.BelowLiquidTrait;
|
import io.anuke.mindustry.entities.traits.BelowLiquidTrait;
|
||||||
import io.anuke.mindustry.entities.traits.DrawTrait;
|
import io.anuke.mindustry.entities.traits.DrawTrait;
|
||||||
|
import io.anuke.mindustry.graphics.Pal;
|
||||||
|
|
||||||
import static io.anuke.mindustry.Vars.groundEffectGroup;
|
import static io.anuke.mindustry.Vars.groundEffectGroup;
|
||||||
|
|
||||||
@@ -14,7 +14,6 @@ import static io.anuke.mindustry.Vars.groundEffectGroup;
|
|||||||
* Class for creating block rubble on the ground.
|
* Class for creating block rubble on the ground.
|
||||||
*/
|
*/
|
||||||
public abstract class Decal extends TimedEntity implements BelowLiquidTrait, DrawTrait{
|
public abstract class Decal extends TimedEntity implements BelowLiquidTrait, DrawTrait{
|
||||||
private static final Color color = Color.valueOf("3a3635");
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float lifetime(){
|
public float lifetime(){
|
||||||
@@ -23,7 +22,7 @@ public abstract class Decal extends TimedEntity implements BelowLiquidTrait, Dra
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void draw(){
|
public void draw(){
|
||||||
Draw.color(color.r, color.g, color.b, 1f - Mathf.curve(fin(), 0.98f));
|
Draw.color(Pal.rubble.r, Pal.rubble.g, Pal.rubble.b, 1f - Mathf.curve(fin(), 0.98f));
|
||||||
drawDecal();
|
drawDecal();
|
||||||
Draw.color();
|
Draw.color();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,11 @@
|
|||||||
package io.anuke.mindustry.entities.effect;
|
package io.anuke.mindustry.entities.effect;
|
||||||
|
|
||||||
|
import io.anuke.annotations.Annotations.Remote;
|
||||||
import io.anuke.arc.collection.IntMap;
|
import io.anuke.arc.collection.IntMap;
|
||||||
import io.anuke.arc.math.Mathf;
|
import io.anuke.arc.math.Mathf;
|
||||||
import io.anuke.arc.math.geom.Geometry;
|
import io.anuke.arc.math.geom.Geometry;
|
||||||
import io.anuke.arc.math.geom.Point2;
|
import io.anuke.arc.math.geom.Point2;
|
||||||
import io.anuke.arc.util.Structs;
|
import io.anuke.arc.util.*;
|
||||||
import io.anuke.arc.util.Time;
|
|
||||||
import io.anuke.arc.util.pooling.Pool.Poolable;
|
|
||||||
import io.anuke.arc.util.pooling.Pools;
|
|
||||||
import io.anuke.mindustry.content.*;
|
import io.anuke.mindustry.content.*;
|
||||||
import io.anuke.mindustry.entities.*;
|
import io.anuke.mindustry.entities.*;
|
||||||
import io.anuke.mindustry.entities.impl.TimedEntity;
|
import io.anuke.mindustry.entities.impl.TimedEntity;
|
||||||
@@ -22,7 +20,7 @@ import java.io.*;
|
|||||||
|
|
||||||
import static io.anuke.mindustry.Vars.*;
|
import static io.anuke.mindustry.Vars.*;
|
||||||
|
|
||||||
public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable{
|
public class Fire extends TimedEntity implements SaveTrait, SyncTrait{
|
||||||
private static final IntMap<Fire> map = new IntMap<>();
|
private static final IntMap<Fire> map = new IntMap<>();
|
||||||
private static final float baseLifetime = 1000f, spreadChance = 0.05f, fireballChance = 0.07f;
|
private static final float baseLifetime = 1000f, spreadChance = 0.05f, fireballChance = 0.07f;
|
||||||
|
|
||||||
@@ -36,6 +34,11 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable{
|
|||||||
public Fire(){
|
public Fire(){
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Remote
|
||||||
|
public static void onRemoveFire(int fid){
|
||||||
|
fireGroup.removeByID(fid);
|
||||||
|
}
|
||||||
|
|
||||||
/** Start a fire on the tile. If there already is a file there, refreshes its lifetime. */
|
/** Start a fire on the tile. If there already is a file there, refreshes its lifetime. */
|
||||||
public static void create(Tile tile){
|
public static void create(Tile tile){
|
||||||
if(Net.client() || tile == null) return; //not clientside.
|
if(Net.client() || tile == null) return; //not clientside.
|
||||||
@@ -43,7 +46,7 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable{
|
|||||||
Fire fire = map.get(tile.pos());
|
Fire fire = map.get(tile.pos());
|
||||||
|
|
||||||
if(fire == null){
|
if(fire == null){
|
||||||
fire = Pools.obtain(Fire.class, Fire::new);
|
fire = new Fire();
|
||||||
fire.tile = tile;
|
fire.tile = tile;
|
||||||
fire.lifetime = baseLifetime;
|
fire.lifetime = baseLifetime;
|
||||||
fire.set(tile.worldx(), tile.worldy());
|
fire.set(tile.worldx(), tile.worldy());
|
||||||
@@ -94,12 +97,12 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable{
|
|||||||
|
|
||||||
time = Mathf.clamp(time + Time.delta(), 0, lifetime());
|
time = Mathf.clamp(time + Time.delta(), 0, lifetime());
|
||||||
|
|
||||||
if(time >= lifetime() || tile == null){
|
if(Net.client()){
|
||||||
remove();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Net.client()){
|
if(time >= lifetime() || tile == null){
|
||||||
|
remove();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,6 +179,7 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable{
|
|||||||
|
|
||||||
x = Pos.x(pos) * tilesize;
|
x = Pos.x(pos) * tilesize;
|
||||||
y = Pos.y(pos) * tilesize;
|
y = Pos.y(pos) * tilesize;
|
||||||
|
tile = world.tile(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -184,6 +188,7 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable{
|
|||||||
tile = null;
|
tile = null;
|
||||||
baseFlammability = -1;
|
baseFlammability = -1;
|
||||||
puddleFlammability = 0f;
|
puddleFlammability = 0f;
|
||||||
|
incrementID();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -198,9 +203,9 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait, Poolable{
|
|||||||
@Override
|
@Override
|
||||||
public void removed(){
|
public void removed(){
|
||||||
if(tile != null){
|
if(tile != null){
|
||||||
|
Call.onRemoveFire(id);
|
||||||
map.remove(tile.pos());
|
map.remove(tile.pos());
|
||||||
}
|
}
|
||||||
reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -58,4 +58,9 @@ public abstract class BaseEntity implements Entity{
|
|||||||
public String toString(){
|
public String toString(){
|
||||||
return getClass() + " " + id;
|
return getClass() + " " + id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Increments this entity's ID. Used for pooled entities.*/
|
||||||
|
public void incrementID(){
|
||||||
|
id = lastid++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ public interface BuilderTrait extends Entity, TeamTrait{
|
|||||||
output.writeInt(Pos.get(request.x, request.y));
|
output.writeInt(Pos.get(request.x, request.y));
|
||||||
output.writeFloat(request.progress);
|
output.writeFloat(request.progress);
|
||||||
if(!request.breaking){
|
if(!request.breaking){
|
||||||
output.writeByte(request.block.id);
|
output.writeShort(request.block.id);
|
||||||
output.writeByte(request.rotation);
|
output.writeByte(request.rotation);
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
@@ -189,7 +189,7 @@ public interface BuilderTrait extends Entity, TeamTrait{
|
|||||||
if(type == 1){ //remove
|
if(type == 1){ //remove
|
||||||
request = new BuildRequest(Pos.x(position), Pos.y(position));
|
request = new BuildRequest(Pos.x(position), Pos.y(position));
|
||||||
}else{ //place
|
}else{ //place
|
||||||
byte block = input.readByte();
|
short block = input.readShort();
|
||||||
byte rotation = input.readByte();
|
byte rotation = input.readByte();
|
||||||
request = new BuildRequest(Pos.x(position), Pos.y(position), rotation, content.block(block));
|
request = new BuildRequest(Pos.x(position), Pos.y(position), rotation, content.block(block));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import io.anuke.mindustry.gen.Call;
|
|||||||
import io.anuke.mindustry.net.Net;
|
import io.anuke.mindustry.net.Net;
|
||||||
import io.anuke.mindustry.type.*;
|
import io.anuke.mindustry.type.*;
|
||||||
import io.anuke.mindustry.world.Tile;
|
import io.anuke.mindustry.world.Tile;
|
||||||
|
import io.anuke.mindustry.world.blocks.units.UnitFactory.UnitFactoryEntity;
|
||||||
import io.anuke.mindustry.world.meta.BlockFlag;
|
import io.anuke.mindustry.world.meta.BlockFlag;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
@@ -264,7 +265,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
|||||||
|
|
||||||
avoidOthers();
|
avoidOthers();
|
||||||
|
|
||||||
if(spawner != noSpawner && (world.tile(spawner) == null || world.tile(spawner).entity == null)){
|
if(spawner != noSpawner && (world.tile(spawner) == null || !(world.tile(spawner).entity instanceof UnitFactoryEntity))){
|
||||||
kill();
|
kill();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -559,7 +559,7 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{
|
|||||||
updateShooting(); //server simulates player shooting
|
updateShooting(); //server simulates player shooting
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}else{
|
}else if(world.isZone()){
|
||||||
//unlock mech when used
|
//unlock mech when used
|
||||||
data.unlockContent(mech);
|
data.unlockContent(mech);
|
||||||
}
|
}
|
||||||
@@ -665,10 +665,10 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{
|
|||||||
attractDst = 0f;
|
attractDst = 0f;
|
||||||
|
|
||||||
if(tapping){
|
if(tapping){
|
||||||
velocity.setAngle(Mathf.slerpDelta(velocity.angle(), angleTo(moveTarget), 0.1f));
|
velocity.setAngle(angleTo(moveTarget));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dst(moveTarget) < 2f){
|
if(dst(moveTarget) <= 2f * Time.delta()){
|
||||||
if(tapping){
|
if(tapping){
|
||||||
Tile tile = ((TileEntity)moveTarget).tile;
|
Tile tile = ((TileEntity)moveTarget).tile;
|
||||||
tile.block().tapped(tile, this);
|
tile.block().tapped(tile, this);
|
||||||
@@ -680,7 +680,7 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{
|
|||||||
moveTarget = null;
|
moveTarget = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
movement.set(targetX - x, targetY - y).limit(isBoosting && !mech.flying ? mech.boostSpeed : mech.speed);
|
movement.set((targetX - x) / Time.delta(), (targetY - y) / Time.delta()).limit(isBoosting && !mech.flying ? mech.boostSpeed : mech.speed);
|
||||||
movement.setAngle(Mathf.slerp(movement.angle(), velocity.angle(), 0.05f));
|
movement.setAngle(Mathf.slerp(movement.angle(), velocity.angle(), 0.05f));
|
||||||
|
|
||||||
if(dst(targetX, targetY) < attractDst){
|
if(dst(targetX, targetY) < attractDst){
|
||||||
@@ -795,7 +795,7 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isShooting(){
|
public boolean isShooting(){
|
||||||
return isShooting && (!isBoosting || mech.flying);
|
return isShooting && (!isBoosting || mech.flying) && mining == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateRespawning(){
|
public void updateRespawning(){
|
||||||
|
|||||||
@@ -9,8 +9,7 @@ import io.anuke.arc.graphics.g2d.TextureRegion;
|
|||||||
import io.anuke.arc.math.Mathf;
|
import io.anuke.arc.math.Mathf;
|
||||||
import io.anuke.arc.math.geom.Geometry;
|
import io.anuke.arc.math.geom.Geometry;
|
||||||
import io.anuke.arc.math.geom.Vector2;
|
import io.anuke.arc.math.geom.Vector2;
|
||||||
import io.anuke.arc.util.Time;
|
import io.anuke.arc.util.*;
|
||||||
import io.anuke.arc.util.Tmp;
|
|
||||||
import io.anuke.mindustry.content.Blocks;
|
import io.anuke.mindustry.content.Blocks;
|
||||||
import io.anuke.mindustry.content.Fx;
|
import io.anuke.mindustry.content.Fx;
|
||||||
import io.anuke.mindustry.entities.*;
|
import io.anuke.mindustry.entities.*;
|
||||||
@@ -256,6 +255,16 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
|||||||
kill();
|
kill();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//apply knockback based on spawns
|
||||||
|
if(getTeam() != waveTeam){
|
||||||
|
float relativeSize = state.rules.dropZoneRadius + getSize()/2f + 1f;
|
||||||
|
for(Tile spawn : world.spawner.getGroundSpawns()){
|
||||||
|
if(withinDst(spawn.worldx(), spawn.worldy(), relativeSize)){
|
||||||
|
velocity.add(Tmp.v1.set(this).sub(spawn.worldx(), spawn.worldy()).setLength(0.1f + 1f - dst(spawn) / relativeSize).scl(0.45f * Time.delta()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(isFlying()){
|
if(isFlying()){
|
||||||
drownTime = 0f;
|
drownTime = 0f;
|
||||||
move(velocity.x * Time.delta(), velocity.y * Time.delta());
|
move(velocity.x * Time.delta(), velocity.y * Time.delta());
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package io.anuke.mindustry.game;
|
package io.anuke.mindustry.game;
|
||||||
|
|
||||||
import io.anuke.arc.Events.Event;
|
|
||||||
import io.anuke.mindustry.core.GameState.State;
|
import io.anuke.mindustry.core.GameState.State;
|
||||||
import io.anuke.mindustry.entities.traits.BuilderTrait;
|
import io.anuke.mindustry.entities.traits.BuilderTrait;
|
||||||
import io.anuke.mindustry.entities.type.Unit;
|
import io.anuke.mindustry.entities.type.Unit;
|
||||||
@@ -10,7 +9,7 @@ import io.anuke.mindustry.world.Tile;
|
|||||||
public class EventType{
|
public class EventType{
|
||||||
|
|
||||||
/** Called when a zone's requirements are met. */
|
/** Called when a zone's requirements are met. */
|
||||||
public static class ZoneRequireCompleteEvent implements Event{
|
public static class ZoneRequireCompleteEvent{
|
||||||
public final Zone zone, required;
|
public final Zone zone, required;
|
||||||
|
|
||||||
public ZoneRequireCompleteEvent(Zone zone, Zone required){
|
public ZoneRequireCompleteEvent(Zone zone, Zone required){
|
||||||
@@ -20,7 +19,7 @@ public class EventType{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Called when a zone's requirements are met. */
|
/** Called when a zone's requirements are met. */
|
||||||
public static class ZoneConfigureCompleteEvent implements Event{
|
public static class ZoneConfigureCompleteEvent{
|
||||||
public final Zone zone;
|
public final Zone zone;
|
||||||
|
|
||||||
public ZoneConfigureCompleteEvent(Zone zone){
|
public ZoneConfigureCompleteEvent(Zone zone){
|
||||||
@@ -29,23 +28,23 @@ public class EventType{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Called when the game is first loaded. */
|
/** Called when the game is first loaded. */
|
||||||
public static class GameLoadEvent implements Event{
|
public static class GameLoadEvent{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class PlayEvent implements Event{
|
public static class PlayEvent{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ResetEvent implements Event{
|
public static class ResetEvent{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class WaveEvent implements Event{
|
public static class WaveEvent{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class GameOverEvent implements Event{
|
public static class GameOverEvent{
|
||||||
public final Team winner;
|
public final Team winner;
|
||||||
|
|
||||||
public GameOverEvent(Team winner){
|
public GameOverEvent(Team winner){
|
||||||
@@ -54,12 +53,12 @@ public class EventType{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Called when a game begins and the world is loaded. */
|
/** Called when a game begins and the world is loaded. */
|
||||||
public static class WorldLoadEvent implements Event{
|
public static class WorldLoadEvent{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Called from the logic thread. Do not access graphics here! */
|
/** Called from the logic thread. Do not access graphics here! */
|
||||||
public static class TileChangeEvent implements Event{
|
public static class TileChangeEvent{
|
||||||
public final Tile tile;
|
public final Tile tile;
|
||||||
|
|
||||||
public TileChangeEvent(Tile tile){
|
public TileChangeEvent(Tile tile){
|
||||||
@@ -67,7 +66,7 @@ public class EventType{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class StateChangeEvent implements Event{
|
public static class StateChangeEvent{
|
||||||
public final State from, to;
|
public final State from, to;
|
||||||
|
|
||||||
public StateChangeEvent(State from, State to){
|
public StateChangeEvent(State from, State to){
|
||||||
@@ -76,7 +75,7 @@ public class EventType{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class UnlockEvent implements Event{
|
public static class UnlockEvent{
|
||||||
public final UnlockableContent content;
|
public final UnlockableContent content;
|
||||||
|
|
||||||
public UnlockEvent(UnlockableContent content){
|
public UnlockEvent(UnlockableContent content){
|
||||||
@@ -88,7 +87,7 @@ public class EventType{
|
|||||||
* Called when block building begins by placing down the BuildBlock.
|
* Called when block building begins by placing down the BuildBlock.
|
||||||
* The tile's block will nearly always be a BuildBlock.
|
* The tile's block will nearly always be a BuildBlock.
|
||||||
*/
|
*/
|
||||||
public static class BlockBuildBeginEvent implements Event{
|
public static class BlockBuildBeginEvent{
|
||||||
public final Tile tile;
|
public final Tile tile;
|
||||||
public final Team team;
|
public final Team team;
|
||||||
public final boolean breaking;
|
public final boolean breaking;
|
||||||
@@ -100,7 +99,7 @@ public class EventType{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class BlockBuildEndEvent implements Event{
|
public static class BlockBuildEndEvent{
|
||||||
public final Tile tile;
|
public final Tile tile;
|
||||||
public final Team team;
|
public final Team team;
|
||||||
public final boolean breaking;
|
public final boolean breaking;
|
||||||
@@ -116,7 +115,7 @@ public class EventType{
|
|||||||
* Called when a player or drone begins building something.
|
* Called when a player or drone begins building something.
|
||||||
* This does not necessarily happen when a new BuildBlock is created.
|
* This does not necessarily happen when a new BuildBlock is created.
|
||||||
*/
|
*/
|
||||||
public static class BuildSelectEvent implements Event{
|
public static class BuildSelectEvent{
|
||||||
public final Tile tile;
|
public final Tile tile;
|
||||||
public final Team team;
|
public final Team team;
|
||||||
public final BuilderTrait builder;
|
public final BuilderTrait builder;
|
||||||
@@ -130,7 +129,7 @@ public class EventType{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class BlockDestroyEvent implements Event{
|
public static class BlockDestroyEvent{
|
||||||
public final Tile tile;
|
public final Tile tile;
|
||||||
|
|
||||||
public BlockDestroyEvent(Tile tile){
|
public BlockDestroyEvent(Tile tile){
|
||||||
@@ -138,7 +137,7 @@ public class EventType{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class UnitDestroyEvent implements Event{
|
public static class UnitDestroyEvent{
|
||||||
public final Unit unit;
|
public final Unit unit;
|
||||||
|
|
||||||
public UnitDestroyEvent(Unit unit){
|
public UnitDestroyEvent(Unit unit){
|
||||||
@@ -146,7 +145,7 @@ public class EventType{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ResizeEvent implements Event{
|
public static class ResizeEvent{
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,10 +28,10 @@ public enum Gamemode{
|
|||||||
rules.respawnTime = 60 * 10;
|
rules.respawnTime = 60 * 10;
|
||||||
rules.buildCostMultiplier = 0.5f;
|
rules.buildCostMultiplier = 0.5f;
|
||||||
rules.buildSpeedMultiplier = 2f;
|
rules.buildSpeedMultiplier = 2f;
|
||||||
rules.playerDamageMultiplier = 0.45f;
|
rules.playerDamageMultiplier = 0.33f;
|
||||||
rules.playerHealthMultiplier = 0.8f;
|
rules.playerHealthMultiplier = 0.5f;
|
||||||
rules.unitBuildSpeedMultiplier = 3f;
|
rules.unitBuildSpeedMultiplier = 3f;
|
||||||
rules.unitHealthMultiplier = 2f;
|
rules.unitHealthMultiplier = 3f;
|
||||||
rules.attackMode = true;
|
rules.attackMode = true;
|
||||||
}),
|
}),
|
||||||
editor(true, rules -> {
|
editor(true, rules -> {
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ public class Teams{
|
|||||||
/** Returns whether a team is active, e.g. whether it has any cores remaining. */
|
/** Returns whether a team is active, e.g. whether it has any cores remaining. */
|
||||||
public boolean isActive(Team team){
|
public boolean isActive(Team team){
|
||||||
//the enemy wave team is always active
|
//the enemy wave team is always active
|
||||||
return (Vars.state.rules.waves && team == Vars.waveTeam) || get(team).cores.size > 0;
|
return team == Vars.waveTeam || get(team).cores.size > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns a set of all teams that are enemies of this team. */
|
/** Returns a set of all teams that are enemies of this team. */
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ public class Pal{
|
|||||||
darkishGray = new Color(0.3f, 0.3f, 0.3f, 1f),
|
darkishGray = new Color(0.3f, 0.3f, 0.3f, 1f),
|
||||||
darkerGray = new Color(0.2f, 0.2f, 0.2f, 1f),
|
darkerGray = new Color(0.2f, 0.2f, 0.2f, 1f),
|
||||||
ammo = Color.valueOf("ff8947"),
|
ammo = Color.valueOf("ff8947"),
|
||||||
|
rubble = Color.valueOf("1c1817"),
|
||||||
|
|
||||||
boostTo = Color.valueOf("ffad4d"),
|
boostTo = Color.valueOf("ffad4d"),
|
||||||
boostFrom = Color.valueOf("ff7f57"),
|
boostFrom = Color.valueOf("ff7f57"),
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ public class LegacyMapIO{
|
|||||||
for(int x = 0; x < map.width; x++){
|
for(int x = 0; x < map.width; x++){
|
||||||
for(int y = 0; y < map.height; y++){
|
for(int y = 0; y < map.height; y++){
|
||||||
tiles[x][y] = new CachedTile();
|
tiles[x][y] = new CachedTile();
|
||||||
|
tiles[x][y].x = (short)x;
|
||||||
|
tiles[x][y].y = (short)y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state.rules.spawns = groups;
|
state.rules.spawns = groups;
|
||||||
@@ -53,6 +55,9 @@ public class LegacyMapIO{
|
|||||||
|
|
||||||
//meta is uncompressed
|
//meta is uncompressed
|
||||||
int version = stream.readInt();
|
int version = stream.readInt();
|
||||||
|
if(version != 1){
|
||||||
|
throw new IOException("Outdated legacy map format");
|
||||||
|
}
|
||||||
int build = stream.readInt();
|
int build = stream.readInt();
|
||||||
short width = stream.readShort(), height = stream.readShort();
|
short width = stream.readShort(), height = stream.readShort();
|
||||||
byte tagAmount = stream.readByte();
|
byte tagAmount = stream.readByte();
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ public abstract class SaveVersion extends SaveFileReader{
|
|||||||
state.wavetime = map.getFloat("wavetime", state.rules.waveSpacing);
|
state.wavetime = map.getFloat("wavetime", state.rules.waveSpacing);
|
||||||
state.stats = JsonIO.read(Stats.class, map.get("stats", "{}"));
|
state.stats = JsonIO.read(Stats.class, map.get("stats", "{}"));
|
||||||
state.rules = JsonIO.read(Rules.class, map.get("rules", "{}"));
|
state.rules = JsonIO.read(Rules.class, map.get("rules", "{}"));
|
||||||
|
if(state.rules.spawns.isEmpty()) state.rules.spawns = DefaultWaves.get();
|
||||||
Map worldmap = world.maps.byName(map.get("mapname", "\\\\\\"));
|
Map worldmap = world.maps.byName(map.get("mapname", "\\\\\\"));
|
||||||
world.setMap(worldmap == null ? new Map(StringMap.of(
|
world.setMap(worldmap == null ? new Map(StringMap.of(
|
||||||
"name", map.get("mapname", "Unknown"),
|
"name", map.get("mapname", "Unknown"),
|
||||||
@@ -170,10 +171,14 @@ public abstract class SaveVersion extends SaveFileReader{
|
|||||||
tile.setBlock(block);
|
tile.setBlock(block);
|
||||||
|
|
||||||
if(tile.entity != null){
|
if(tile.entity != null){
|
||||||
readChunk(stream, true, in -> {
|
try{
|
||||||
byte version = in.readByte();
|
readChunk(stream, true, in -> {
|
||||||
tile.entity.read(in, version);
|
byte version = in.readByte();
|
||||||
});
|
tile.entity.read(in, version);
|
||||||
|
});
|
||||||
|
}catch(Exception e){
|
||||||
|
throw new IOException("Failed to read tile entity of block: " + block, e);
|
||||||
|
}
|
||||||
}else{
|
}else{
|
||||||
int consecutives = stream.readUnsignedByte();
|
int consecutives = stream.readUnsignedByte();
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import io.anuke.arc.collection.StringMap;
|
|||||||
import io.anuke.arc.files.FileHandle;
|
import io.anuke.arc.files.FileHandle;
|
||||||
import io.anuke.arc.graphics.Texture;
|
import io.anuke.arc.graphics.Texture;
|
||||||
import io.anuke.mindustry.Vars;
|
import io.anuke.mindustry.Vars;
|
||||||
|
import io.anuke.mindustry.game.DefaultWaves;
|
||||||
import io.anuke.mindustry.game.Rules;
|
import io.anuke.mindustry.game.Rules;
|
||||||
import io.anuke.mindustry.io.JsonIO;
|
import io.anuke.mindustry.io.JsonIO;
|
||||||
|
|
||||||
@@ -57,7 +58,9 @@ public class Map implements Comparable<Map>{
|
|||||||
|
|
||||||
/** This creates a new instance.*/
|
/** This creates a new instance.*/
|
||||||
public Rules rules(){
|
public Rules rules(){
|
||||||
return JsonIO.read(Rules.class, tags.get("rules", "{}"));
|
Rules result = JsonIO.read(Rules.class, tags.get("rules", "{}"));
|
||||||
|
if(result.spawns.isEmpty()) result.spawns = DefaultWaves.get();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Whether this map has a core of the enemy 'wave' team. Default: true.
|
/** Whether this map has a core of the enemy 'wave' team. Default: true.
|
||||||
|
|||||||
@@ -3,12 +3,13 @@ package io.anuke.mindustry.maps;
|
|||||||
import io.anuke.arc.Core;
|
import io.anuke.arc.Core;
|
||||||
import io.anuke.arc.collection.*;
|
import io.anuke.arc.collection.*;
|
||||||
import io.anuke.arc.files.FileHandle;
|
import io.anuke.arc.files.FileHandle;
|
||||||
|
import io.anuke.arc.function.ExceptionRunnable;
|
||||||
import io.anuke.arc.graphics.Texture;
|
import io.anuke.arc.graphics.Texture;
|
||||||
import io.anuke.arc.util.Disposable;
|
import io.anuke.arc.util.*;
|
||||||
import io.anuke.arc.util.Log;
|
|
||||||
import io.anuke.arc.util.serialization.Json;
|
import io.anuke.arc.util.serialization.Json;
|
||||||
import io.anuke.mindustry.game.SpawnGroup;
|
import io.anuke.mindustry.game.SpawnGroup;
|
||||||
import io.anuke.mindustry.io.*;
|
import io.anuke.mindustry.io.LegacyMapIO;
|
||||||
|
import io.anuke.mindustry.io.MapIO;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
@@ -17,7 +18,7 @@ import static io.anuke.mindustry.Vars.*;
|
|||||||
|
|
||||||
public class Maps implements Disposable{
|
public class Maps implements Disposable{
|
||||||
/** List of all built-in maps. Filenames only. */
|
/** List of all built-in maps. Filenames only. */
|
||||||
private static final String[] defaultMapNames = {"fortress"};
|
private static final String[] defaultMapNames = {"fortress", "shoreline", "labyrinth", "islands"};
|
||||||
/** All maps stored in an ordered array. */
|
/** All maps stored in an ordered array. */
|
||||||
private Array<Map> maps = new Array<>();
|
private Array<Map> maps = new Array<>();
|
||||||
/** Serializer for meta. */
|
/** Serializer for meta. */
|
||||||
@@ -116,6 +117,14 @@ public class Maps implements Disposable{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Creates a legacy map by converting it to a non-legacy map and pasting it in a temp directory.
|
||||||
|
* Should be followed up by {@link #importMap(FileHandle)} .*/
|
||||||
|
public Map makeLegacyMap(FileHandle file) throws IOException{
|
||||||
|
FileHandle dst = tmpDirectory.child("conversion_map." + mapExtension);
|
||||||
|
LegacyMapIO.convertMap(file, dst);
|
||||||
|
return MapIO.createMap(dst, true);
|
||||||
|
}
|
||||||
|
|
||||||
/** Import a map, then save it. This updates all values and stored data necessary. */
|
/** Import a map, then save it. This updates all values and stored data necessary. */
|
||||||
public void importMap(FileHandle file) throws IOException{
|
public void importMap(FileHandle file) throws IOException{
|
||||||
FileHandle dest = findFile();
|
FileHandle dest = findFile();
|
||||||
@@ -124,6 +133,24 @@ public class Maps implements Disposable{
|
|||||||
loadMap(dest, true);
|
loadMap(dest, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Attempts to run the following code;
|
||||||
|
* catches any errors and attempts to display them in a readable way.*/
|
||||||
|
public void tryCatchMapError(ExceptionRunnable run){
|
||||||
|
try{
|
||||||
|
run.run();
|
||||||
|
}catch(Exception e){
|
||||||
|
Log.err(e);
|
||||||
|
|
||||||
|
if("Outdated legacy map format".equals(e.getMessage())){
|
||||||
|
ui.showError("$editor.errorlegacy");
|
||||||
|
}else if(e.getMessage() != null && e.getMessage().contains("Incorrect header!")){
|
||||||
|
ui.showError("$editor.errorheader");
|
||||||
|
}else{
|
||||||
|
ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, true)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** Removes a map completely. */
|
/** Removes a map completely. */
|
||||||
public void removeMap(Map map){
|
public void removeMap(Map map){
|
||||||
if(map.texture != null){
|
if(map.texture != null){
|
||||||
|
|||||||
@@ -6,8 +6,7 @@ import io.anuke.arc.collection.*;
|
|||||||
import io.anuke.arc.function.BiConsumer;
|
import io.anuke.arc.function.BiConsumer;
|
||||||
import io.anuke.arc.function.Consumer;
|
import io.anuke.arc.function.Consumer;
|
||||||
import io.anuke.arc.net.HttpRequestBuilder;
|
import io.anuke.arc.net.HttpRequestBuilder;
|
||||||
import io.anuke.arc.util.Log;
|
import io.anuke.arc.util.*;
|
||||||
import io.anuke.arc.util.Time;
|
|
||||||
import io.anuke.arc.util.pooling.Pools;
|
import io.anuke.arc.util.pooling.Pools;
|
||||||
import io.anuke.mindustry.core.Platform;
|
import io.anuke.mindustry.core.Platform;
|
||||||
import io.anuke.mindustry.gen.Call;
|
import io.anuke.mindustry.gen.Call;
|
||||||
@@ -67,7 +66,7 @@ public class Net{
|
|||||||
}else if(error.equals("alreadyconnected")){
|
}else if(error.equals("alreadyconnected")){
|
||||||
error = Core.bundle.get("error.alreadyconnected");
|
error = Core.bundle.get("error.alreadyconnected");
|
||||||
}else if(!error.isEmpty()){
|
}else if(!error.isEmpty()){
|
||||||
error = Core.bundle.get("error.any") + "\n" + t.getClass().getSimpleName() + "\n" + (t.getMessage() == null ? "" : t.getMessage());
|
error = Core.bundle.get("error.any") + "\n" + Strings.parseException(e, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.showText("", Core.bundle.format("connectfail", error));
|
ui.showText("", Core.bundle.format("connectfail", error));
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import io.anuke.mindustry.type.ItemStack;
|
|||||||
|
|
||||||
/** An item image with text. */
|
/** An item image with text. */
|
||||||
public class ItemDisplay extends Table{
|
public class ItemDisplay extends Table{
|
||||||
|
public final Item item;
|
||||||
|
public final int amount;
|
||||||
|
|
||||||
public ItemDisplay(Item item){
|
public ItemDisplay(Item item){
|
||||||
this(item, 0);
|
this(item, 0);
|
||||||
@@ -14,5 +16,8 @@ public class ItemDisplay extends Table{
|
|||||||
public ItemDisplay(Item item, int amount){
|
public ItemDisplay(Item item, int amount){
|
||||||
add(new ItemImage(new ItemStack(item, amount))).size(8 * 4);
|
add(new ItemImage(new ItemStack(item, amount))).size(8 * 4);
|
||||||
add(item.localizedName()).padLeft(4);
|
add(item.localizedName()).padLeft(4);
|
||||||
|
|
||||||
|
this.item = item;
|
||||||
|
this.amount = amount;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,8 +10,15 @@ import io.anuke.mindustry.world.meta.StatUnit;
|
|||||||
|
|
||||||
/** An ItemDisplay, but for liquids. */
|
/** An ItemDisplay, but for liquids. */
|
||||||
public class LiquidDisplay extends Table{
|
public class LiquidDisplay extends Table{
|
||||||
|
public final Liquid liquid;
|
||||||
|
public final float amount;
|
||||||
|
public final boolean perSecond;
|
||||||
|
|
||||||
public LiquidDisplay(Liquid liquid, float amount, boolean perSecond){
|
public LiquidDisplay(Liquid liquid, float amount, boolean perSecond){
|
||||||
|
this.liquid = liquid;
|
||||||
|
this.amount = amount;
|
||||||
|
this.perSecond = perSecond;
|
||||||
|
|
||||||
add(new Stack(){{
|
add(new Stack(){{
|
||||||
add(new Image(liquid.getContentIcon()));
|
add(new Image(liquid.getContentIcon()));
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ import io.anuke.mindustry.ui.BorderImage;
|
|||||||
|
|
||||||
import static io.anuke.mindustry.Vars.world;
|
import static io.anuke.mindustry.Vars.world;
|
||||||
|
|
||||||
public class CustomGameDialog extends FloatingDialog{
|
public class
|
||||||
|
CustomGameDialog extends FloatingDialog{
|
||||||
private MapPlayDialog dialog = new MapPlayDialog();
|
private MapPlayDialog dialog = new MapPlayDialog();
|
||||||
|
|
||||||
public CustomGameDialog(){
|
public CustomGameDialog(){
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import io.anuke.arc.scene.ui.layout.Table;
|
|||||||
import io.anuke.arc.scene.ui.layout.Unit;
|
import io.anuke.arc.scene.ui.layout.Unit;
|
||||||
import io.anuke.arc.util.*;
|
import io.anuke.arc.util.*;
|
||||||
import io.anuke.arc.util.pooling.Pools;
|
import io.anuke.arc.util.pooling.Pools;
|
||||||
|
import io.anuke.mindustry.Vars;
|
||||||
import io.anuke.mindustry.core.Platform;
|
import io.anuke.mindustry.core.Platform;
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -29,12 +30,26 @@ public class FileChooser extends FloatingDialog{
|
|||||||
private Predicate<FileHandle> filter;
|
private Predicate<FileHandle> filter;
|
||||||
private Consumer<FileHandle> selectListener;
|
private Consumer<FileHandle> selectListener;
|
||||||
private boolean open;
|
private boolean open;
|
||||||
|
private int lastWidth = Core.graphics.getWidth(), lastHeight = Core.graphics.getHeight();
|
||||||
|
|
||||||
|
public static final Predicate<String> pngFiles = str -> str.equals("png");
|
||||||
|
public static final Predicate<String> anyMapFiles = str -> str.equals(Vars.oldMapExtension) || str.equals(Vars.mapExtension);
|
||||||
|
public static final Predicate<String> mapFiles = str -> str.equals(Vars.mapExtension);
|
||||||
|
public static final Predicate<String> saveFiles = str -> str.equals(Vars.saveExtension);
|
||||||
|
|
||||||
public FileChooser(String title, Predicate<FileHandle> filter, boolean open, Consumer<FileHandle> result){
|
public FileChooser(String title, Predicate<FileHandle> filter, boolean open, Consumer<FileHandle> result){
|
||||||
super(title);
|
super(title);
|
||||||
this.open = open;
|
this.open = open;
|
||||||
this.filter = filter;
|
this.filter = filter;
|
||||||
this.selectListener = result;
|
this.selectListener = result;
|
||||||
|
|
||||||
|
update(() -> {
|
||||||
|
if(Core.graphics.getWidth() != lastWidth || Core.graphics.getHeight() != lastHeight){
|
||||||
|
updateFiles(false);
|
||||||
|
lastHeight = Core.graphics.getHeight();
|
||||||
|
lastWidth = Core.graphics.getWidth();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupWidgets(){
|
private void setupWidgets(){
|
||||||
@@ -268,14 +283,6 @@ public class FileChooser extends FloatingDialog{
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void fileSelected(Consumer<FileHandle> listener){
|
|
||||||
this.selectListener = listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface FileHandleFilter{
|
|
||||||
boolean accept(FileHandle file);
|
|
||||||
}
|
|
||||||
|
|
||||||
public class FileHistory{
|
public class FileHistory{
|
||||||
private Array<FileHandle> history = new Array<>();
|
private Array<FileHandle> history = new Array<>();
|
||||||
private int index;
|
private int index;
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ public class HostDialog extends FloatingDialog{
|
|||||||
Net.host(Vars.port);
|
Net.host(Vars.port);
|
||||||
player.isAdmin = true;
|
player.isAdmin = true;
|
||||||
}catch(IOException e){
|
}catch(IOException e){
|
||||||
ui.showError(Core.bundle.format("server.error", Strings.parseException(e, false)));
|
ui.showError(Core.bundle.format("server.error", Strings.parseException(e, true)));
|
||||||
}
|
}
|
||||||
ui.loadfrag.hide();
|
ui.loadfrag.hide();
|
||||||
hide();
|
hide();
|
||||||
|
|||||||
@@ -90,16 +90,16 @@ public class LoadDialog extends FloatingDialog{
|
|||||||
slot.exportFile(file);
|
slot.exportFile(file);
|
||||||
setup();
|
setup();
|
||||||
}catch(IOException e){
|
}catch(IOException e){
|
||||||
ui.showError(Core.bundle.format("save.export.fail", Strings.parseException(e, false)));
|
ui.showError(Core.bundle.format("save.export.fail", Strings.parseException(e, true)));
|
||||||
}
|
}
|
||||||
}, false, saveExtension);
|
}, false, FileChooser.saveFiles);
|
||||||
}else{
|
}else{
|
||||||
try{
|
try{
|
||||||
FileHandle file = Core.files.local("save-" + slot.getName() + "." + Vars.saveExtension);
|
FileHandle file = Core.files.local("save-" + slot.getName() + "." + Vars.saveExtension);
|
||||||
slot.exportFile(file);
|
slot.exportFile(file);
|
||||||
Platform.instance.shareFile(file);
|
Platform.instance.shareFile(file);
|
||||||
}catch(Exception e){
|
}catch(Exception e){
|
||||||
ui.showError(Core.bundle.format("save.export.fail", Strings.parseException(e, false)));
|
ui.showError(Core.bundle.format("save.export.fail", Strings.parseException(e, true)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}).size(14 * 3).right();
|
}).size(14 * 3).right();
|
||||||
@@ -155,12 +155,12 @@ public class LoadDialog extends FloatingDialog{
|
|||||||
setup();
|
setup();
|
||||||
}catch(IOException e){
|
}catch(IOException e){
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
ui.showError(Core.bundle.format("save.import.fail", Strings.parseException(e, false)));
|
ui.showError(Core.bundle.format("save.import.fail", Strings.parseException(e, true)));
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
ui.showError("$save.import.invalid");
|
ui.showError("$save.import.invalid");
|
||||||
}
|
}
|
||||||
}, true, saveExtension);
|
}, true, FileChooser.saveFiles);
|
||||||
}).fillX().margin(10f).minWidth(300f).height(70f).pad(4f).padRight(-4);
|
}).fillX().margin(10f).minWidth(300f).height(70f).pad(4f).padRight(-4);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public class MapPlayDialog extends FloatingDialog{
|
|||||||
Difficulty difficulty = Difficulty.normal;
|
Difficulty difficulty = Difficulty.normal;
|
||||||
CustomRulesDialog dialog = new CustomRulesDialog();
|
CustomRulesDialog dialog = new CustomRulesDialog();
|
||||||
Rules rules;
|
Rules rules;
|
||||||
Gamemode selectedGamemode;
|
Gamemode selectedGamemode = Gamemode.survival;
|
||||||
|
|
||||||
public MapPlayDialog(){
|
public MapPlayDialog(){
|
||||||
super("");
|
super("");
|
||||||
@@ -28,6 +28,8 @@ public class MapPlayDialog extends FloatingDialog{
|
|||||||
cont.clearChildren();
|
cont.clearChildren();
|
||||||
rules = map.rules();
|
rules = map.rules();
|
||||||
|
|
||||||
|
rules = selectedGamemode.apply(map.rules());
|
||||||
|
|
||||||
Table selmode = new Table();
|
Table selmode = new Table();
|
||||||
selmode.add("$level.mode").colspan(4);
|
selmode.add("$level.mode").colspan(4);
|
||||||
selmode.row();
|
selmode.row();
|
||||||
@@ -43,8 +45,8 @@ public class MapPlayDialog extends FloatingDialog{
|
|||||||
}
|
}
|
||||||
|
|
||||||
modes.addButton(mode.toString(), "toggle", () -> {
|
modes.addButton(mode.toString(), "toggle", () -> {
|
||||||
selectedGamemode = selectedGamemode == mode ? null : mode;
|
selectedGamemode = mode;
|
||||||
rules = selectedGamemode == null ? map.rules() : mode.apply(map.rules());
|
rules = mode.apply(map.rules());
|
||||||
}).update(b -> b.setChecked(selectedGamemode == mode)).size(140f, 54f);
|
}).update(b -> b.setChecked(selectedGamemode == mode)).size(140f, 54f);
|
||||||
if(i++ % 2 == 1) modes.row();
|
if(i++ % 2 == 1) modes.row();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import io.anuke.arc.graphics.Color;
|
|||||||
import io.anuke.arc.scene.event.Touchable;
|
import io.anuke.arc.scene.event.Touchable;
|
||||||
import io.anuke.arc.scene.ui.*;
|
import io.anuke.arc.scene.ui.*;
|
||||||
import io.anuke.arc.scene.ui.layout.Table;
|
import io.anuke.arc.scene.ui.layout.Table;
|
||||||
import io.anuke.arc.util.*;
|
import io.anuke.arc.util.Scaling;
|
||||||
import io.anuke.mindustry.Vars;
|
import io.anuke.mindustry.Vars;
|
||||||
import io.anuke.mindustry.core.Platform;
|
import io.anuke.mindustry.core.Platform;
|
||||||
import io.anuke.mindustry.io.MapIO;
|
import io.anuke.mindustry.io.MapIO;
|
||||||
@@ -23,8 +23,19 @@ public class MapsDialog extends FloatingDialog{
|
|||||||
addCloseButton();
|
addCloseButton();
|
||||||
buttons.addImageTextButton("$editor.importmap", "icon-add", 14 * 2, () -> {
|
buttons.addImageTextButton("$editor.importmap", "icon-add", 14 * 2, () -> {
|
||||||
Platform.instance.showFileChooser("$editor.importmap", "Map File", file -> {
|
Platform.instance.showFileChooser("$editor.importmap", "Map File", file -> {
|
||||||
try{
|
world.maps.tryCatchMapError(() -> {
|
||||||
Map map = MapIO.createMap(file, true);
|
if(MapIO.isImage(file)){
|
||||||
|
ui.showError("$editor.errorimage");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map map;
|
||||||
|
if(file.extension().equalsIgnoreCase(mapExtension)){
|
||||||
|
map = MapIO.createMap(file, true);
|
||||||
|
}else{
|
||||||
|
map = world.maps.makeLegacyMap(file);
|
||||||
|
}
|
||||||
|
|
||||||
String name = map.tags.get("name");
|
String name = map.tags.get("name");
|
||||||
if(name == null){
|
if(name == null){
|
||||||
ui.showError("$editor.errorname");
|
ui.showError("$editor.errorname");
|
||||||
@@ -34,27 +45,21 @@ public class MapsDialog extends FloatingDialog{
|
|||||||
Map conflict = world.maps.all().find(m -> m.name().equals(name));
|
Map conflict = world.maps.all().find(m -> m.name().equals(name));
|
||||||
|
|
||||||
if(conflict != null && !conflict.custom){
|
if(conflict != null && !conflict.custom){
|
||||||
ui.showError(Core.bundle.format("editor.import.exists", name));
|
ui.showInfo(Core.bundle.format("editor.import.exists", name));
|
||||||
}else if(conflict != null){
|
}else if(conflict != null){
|
||||||
ui.showConfirm("$confirm", "$editor.overwrite.confirm", () -> {
|
ui.showConfirm("$confirm", "$editor.overwrite.confirm", () -> {
|
||||||
try{
|
world.maps.tryCatchMapError(() -> {
|
||||||
world.maps.importMap(file);
|
world.maps.importMap(file);
|
||||||
setup();
|
setup();
|
||||||
}catch(Exception e){
|
});
|
||||||
ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, false)));
|
|
||||||
Log.err(e);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}else{
|
}else{
|
||||||
world.maps.importMap(file);
|
world.maps.importMap(map.file);
|
||||||
setup();
|
setup();
|
||||||
}
|
}
|
||||||
|
|
||||||
}catch(Exception e){
|
});
|
||||||
ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, false)));
|
}, true, FileChooser.anyMapFiles);
|
||||||
Log.err(e);
|
|
||||||
}
|
|
||||||
}, true, mapExtension);
|
|
||||||
}).size(230f, 64f);
|
}).size(230f, 64f);
|
||||||
|
|
||||||
shown(this::setup);
|
shown(this::setup);
|
||||||
|
|||||||
@@ -178,7 +178,6 @@ public class SettingsMenuDialog extends SettingsDialog{
|
|||||||
graphics.sliderPref("fpscap", 125, 5, 125, 5, s -> (s > 120 ? Core.bundle.get("setting.fpscap.none") : Core.bundle.format("setting.fpscap.text", s)));
|
graphics.sliderPref("fpscap", 125, 5, 125, 5, s -> (s > 120 ? Core.bundle.get("setting.fpscap.none") : Core.bundle.format("setting.fpscap.text", s)));
|
||||||
graphics.sliderPref("chatopacity", 100, 0, 100, 5, s -> s + "%");
|
graphics.sliderPref("chatopacity", 100, 0, 100, 5, s -> s + "%");
|
||||||
|
|
||||||
|
|
||||||
if(!mobile){
|
if(!mobile){
|
||||||
graphics.checkPref("vsync", true, b -> Core.graphics.setVSync(b));
|
graphics.checkPref("vsync", true, b -> Core.graphics.setVSync(b));
|
||||||
graphics.checkPref("fullscreen", false, b -> {
|
graphics.checkPref("fullscreen", false, b -> {
|
||||||
@@ -221,6 +220,22 @@ public class SettingsMenuDialog extends SettingsDialog{
|
|||||||
graphics.checkPref("animatedshields", !mobile);
|
graphics.checkPref("animatedshields", !mobile);
|
||||||
graphics.checkPref("lasers", true);
|
graphics.checkPref("lasers", true);
|
||||||
graphics.checkPref("pixelate", false);
|
graphics.checkPref("pixelate", false);
|
||||||
|
|
||||||
|
//TODO is this necessary?
|
||||||
|
/*
|
||||||
|
graphics.checkPref("linear", false, b -> {
|
||||||
|
for(Texture tex : Core.atlas.getTextures()){
|
||||||
|
TextureFilter filter = b ? TextureFilter.Linear : TextureFilter.Nearest;
|
||||||
|
tex.setFilter(filter, filter);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if(Core.settings.getBool("linear")){
|
||||||
|
for(Texture tex : Core.atlas.getTextures()){
|
||||||
|
TextureFilter filter = TextureFilter.Linear;
|
||||||
|
tex.setFilter(filter, filter);
|
||||||
|
}
|
||||||
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
private void back(){
|
private void back(){
|
||||||
|
|||||||
@@ -73,8 +73,6 @@ public class Block extends BlockStorage{
|
|||||||
public Layer layer2 = null;
|
public Layer layer2 = null;
|
||||||
/** whether this block can be replaced in all cases */
|
/** whether this block can be replaced in all cases */
|
||||||
public boolean alwaysReplace = false;
|
public boolean alwaysReplace = false;
|
||||||
/** whether this block has instant transfer checking. used for calculations to prevent infinite loops. */
|
|
||||||
public boolean instantTransfer = false;
|
|
||||||
/** The block group. Unless {@link #canReplace} is overriden, blocks in the same group can replace each other. */
|
/** The block group. Unless {@link #canReplace} is overriden, blocks in the same group can replace each other. */
|
||||||
public BlockGroup group = BlockGroup.none;
|
public BlockGroup group = BlockGroup.none;
|
||||||
/** List of block flags. Used for AI indexing. */
|
/** List of block flags. Used for AI indexing. */
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package io.anuke.mindustry.world;
|
package io.anuke.mindustry.world;
|
||||||
|
|
||||||
import io.anuke.arc.collection.IntMap;
|
|
||||||
import io.anuke.mindustry.entities.type.TileEntity;
|
import io.anuke.mindustry.entities.type.TileEntity;
|
||||||
import io.anuke.mindustry.game.Team;
|
import io.anuke.mindustry.game.Team;
|
||||||
import io.anuke.mindustry.world.modules.*;
|
import io.anuke.mindustry.world.modules.*;
|
||||||
@@ -10,7 +9,6 @@ import io.anuke.mindustry.world.modules.*;
|
|||||||
* Prevents garbage when loading previews.
|
* Prevents garbage when loading previews.
|
||||||
*/
|
*/
|
||||||
public class CachedTile extends Tile{
|
public class CachedTile extends Tile{
|
||||||
private static IntMap<TileEntity> entities = new IntMap<>();
|
|
||||||
|
|
||||||
public CachedTile(){
|
public CachedTile(){
|
||||||
super(0, 0);
|
super(0, 0);
|
||||||
@@ -23,7 +21,8 @@ public class CachedTile extends Tile{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void preChanged(){
|
protected void preChanged(){
|
||||||
super.setTeam(Team.none);
|
//this basically overrides the old tile code and doesn't remove from proximity
|
||||||
|
team = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -33,19 +32,14 @@ public class CachedTile extends Tile{
|
|||||||
Block block = block();
|
Block block = block();
|
||||||
|
|
||||||
if(block.hasEntity()){
|
if(block.hasEntity()){
|
||||||
//cache all entity types so only one is ever created per block type. do not add it.
|
TileEntity n = block.newEntity();
|
||||||
if(!entities.containsKey(block.id)){
|
n.cons = new ConsumeModule(entity);
|
||||||
TileEntity n = block.newEntity();
|
n.tile = this;
|
||||||
n.cons = new ConsumeModule(entity);
|
n.block = block;
|
||||||
n.tile = this;
|
if(block.hasItems) n.items = new ItemModule();
|
||||||
if(block.hasItems) n.items = new ItemModule();
|
if(block.hasLiquids) n.liquids = new LiquidModule();
|
||||||
if(block.hasLiquids) n.liquids = new LiquidModule();
|
if(block.hasPower) n.power = new PowerModule();
|
||||||
if(block.hasPower) n.power = new PowerModule();
|
entity = n;
|
||||||
entities.put(block.id, n);
|
|
||||||
}
|
|
||||||
|
|
||||||
entity = entities.get(block.id);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
77
core/src/io/anuke/mindustry/world/DirectionalItemBuffer.java
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
package io.anuke.mindustry.world;
|
||||||
|
|
||||||
|
import io.anuke.annotations.Annotations.Struct;
|
||||||
|
import io.anuke.arc.util.Time;
|
||||||
|
import io.anuke.mindustry.gen.BufferItem;
|
||||||
|
import io.anuke.mindustry.type.Item;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
import static io.anuke.mindustry.Vars.content;
|
||||||
|
|
||||||
|
public class DirectionalItemBuffer{
|
||||||
|
public final long[][] buffers;
|
||||||
|
public final int[] indexes;
|
||||||
|
private final float speed;
|
||||||
|
|
||||||
|
public DirectionalItemBuffer(int capacity, float speed){
|
||||||
|
this.buffers = new long[4][capacity];
|
||||||
|
this.indexes = new int[5];
|
||||||
|
this.speed = speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean accepts(int buffer){
|
||||||
|
return indexes[buffer] < buffers[buffer].length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void accept(int buffer, Item item){
|
||||||
|
if(!accepts(buffer)) return;
|
||||||
|
buffers[buffer][indexes[buffer]++] = BufferItem.get((byte)item.id, Time.time());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Item poll(int buffer){
|
||||||
|
if(indexes[buffer] > 0){
|
||||||
|
long l = buffers[buffer][0];
|
||||||
|
float time = BufferItem.time(l);
|
||||||
|
|
||||||
|
if(Time.time() >= time + speed || Time.time() < time){
|
||||||
|
return content.item(BufferItem.item(l));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove(int buffer){
|
||||||
|
System.arraycopy(buffers[buffer], 1, buffers[buffer], 0, indexes[buffer] - 1);
|
||||||
|
indexes[buffer] --;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void write(DataOutput stream) throws IOException{
|
||||||
|
for(int i = 0; i < 4; i++){
|
||||||
|
stream.writeByte(indexes[i]);
|
||||||
|
stream.writeByte(buffers[i].length);
|
||||||
|
for(long l : buffers[i]){
|
||||||
|
stream.writeLong(l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void read(DataInput stream) throws IOException{
|
||||||
|
for(int i = 0; i < 4; i++){
|
||||||
|
indexes[i] = stream.readByte();
|
||||||
|
byte length = stream.readByte();
|
||||||
|
for(int j = 0; j < length; j++){
|
||||||
|
long value = stream.readLong();
|
||||||
|
if(j < buffers[i].length){
|
||||||
|
buffers[i][j] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Struct
|
||||||
|
class BufferItemStruct{
|
||||||
|
byte item;
|
||||||
|
float time;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -439,6 +439,6 @@ public class Tile implements Position, TargetTrait{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString(){
|
public String toString(){
|
||||||
return floor.name + ":" + block.name + ":" + content.block(overlay) + "[" + x + "," + y + "] " + "entity=" + (entity == null ? "null" : (entity.getClass()));
|
return floor.name + ":" + block.name + ":" + content.block(overlay) + "[" + x + "," + y + "] " + "entity=" + (entity == null ? "null" : (entity.getClass())) + ":" + getTeam();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,7 @@ package io.anuke.mindustry.world.blocks;
|
|||||||
import io.anuke.arc.Core;
|
import io.anuke.arc.Core;
|
||||||
import io.anuke.arc.collection.Array;
|
import io.anuke.arc.collection.Array;
|
||||||
import io.anuke.arc.collection.IntSet;
|
import io.anuke.arc.collection.IntSet;
|
||||||
|
import io.anuke.arc.graphics.Color;
|
||||||
import io.anuke.arc.graphics.g2d.Draw;
|
import io.anuke.arc.graphics.g2d.Draw;
|
||||||
import io.anuke.arc.graphics.g2d.TextureRegion;
|
import io.anuke.arc.graphics.g2d.TextureRegion;
|
||||||
import io.anuke.arc.math.Mathf;
|
import io.anuke.arc.math.Mathf;
|
||||||
@@ -56,6 +57,7 @@ public class Floor extends Block{
|
|||||||
protected byte eq = 0;
|
protected byte eq = 0;
|
||||||
protected Array<Block> blenders = new Array<>();
|
protected Array<Block> blenders = new Array<>();
|
||||||
protected IntSet blended = new IntSet();
|
protected IntSet blended = new IntSet();
|
||||||
|
protected TextureRegion edgeRegion, edgierRegion;
|
||||||
|
|
||||||
public Floor(String name){
|
public Floor(String name){
|
||||||
super(name);
|
super(name);
|
||||||
@@ -82,6 +84,8 @@ public class Floor extends Block{
|
|||||||
edges = Core.atlas.find(name + "-edge").split(size, size);
|
edges = Core.atlas.find(name + "-edge").split(size, size);
|
||||||
}
|
}
|
||||||
region = variantRegions[0];
|
region = variantRegions[0];
|
||||||
|
edgeRegion = Core.atlas.find("edge");
|
||||||
|
edgierRegion = Core.atlas.find("edgier");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -140,14 +144,32 @@ public class Floor extends Block{
|
|||||||
Point2 point = Geometry.d8[i];
|
Point2 point = Geometry.d8[i];
|
||||||
Tile other = tile.getNearby(point);
|
Tile other = tile.getNearby(point);
|
||||||
if(other != null && other.floor() == block){
|
if(other != null && other.floor() == block){
|
||||||
TextureRegion region = edge((Floor)block, type(i), 2 - (point.x + 1), 2 - (point.y + 1));
|
TextureRegion region = edge((Floor)block, 2 - (point.x + 1), 2 - (point.y + 1));
|
||||||
Draw.rect(region, tile.worldx(), tile.worldy());
|
Draw.rect(region, tile.worldx(), tile.worldy());
|
||||||
|
|
||||||
|
if(!sameLayer && block.cacheLayer.ordinal() > cacheLayer.ordinal()){
|
||||||
|
Draw.rect(block.variantRegions()[0], tile.worldx() + point.x*tilesize, tile.worldy() + point.y*tilesize);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//'new' style of edges with shadows instead of colors, not used currently
|
||||||
|
protected void drawEdgesFlat(Tile tile, boolean sameLayer){
|
||||||
|
for(int i = 0; i < 4; i++){
|
||||||
|
Tile other = tile.getNearby(i);
|
||||||
|
if(other != null && doEdge(other.floor(), sameLayer)){
|
||||||
|
Color color = other.floor().color;
|
||||||
|
Draw.color(color.r, color.g, color.b, 1f);
|
||||||
|
Draw.rect(edgeRegion, tile.worldx(), tile.worldy(), i*90);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Draw.color();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
protected TextureRegion[][] edges(){
|
protected TextureRegion[][] edges(){
|
||||||
return ((Floor)blendGroup).edges;
|
return ((Floor)blendGroup).edges;
|
||||||
}
|
}
|
||||||
@@ -160,28 +182,12 @@ public class Floor extends Block{
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int type(int i){
|
|
||||||
if(!eq(i - 1) && !eq(i + 1)){
|
|
||||||
//case 0: touching
|
|
||||||
return 0;
|
|
||||||
}else if(eq(i - 1) && eq(i - 2) && eq(i + 1) && eq(i + 2)){
|
|
||||||
//case 2: surrounded
|
|
||||||
return 2;
|
|
||||||
}else if(eq(i - 1) && eq(i + 1)){
|
|
||||||
//case 1: flat
|
|
||||||
return 1;
|
|
||||||
}else{
|
|
||||||
//case 0 is rounded, so it's the safest choice, should work for most possibilities
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean eq(int i){
|
boolean eq(int i){
|
||||||
return (eq & (1 << Mathf.mod(i, 8))) != 0;
|
return (eq & (1 << Mathf.mod(i, 8))) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
TextureRegion edge(Floor block, int type, int x, int y){
|
TextureRegion edge(Floor block, int x, int y){
|
||||||
return block.edges()[x + type * 3][2 - y];
|
return block.edges()[x][2 - y];
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -16,6 +16,8 @@ import io.anuke.mindustry.world.Tile;
|
|||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|
||||||
|
import static io.anuke.mindustry.Vars.world;
|
||||||
|
|
||||||
public class Door extends Wall{
|
public class Door extends Wall{
|
||||||
protected final Rectangle rect = new Rectangle();
|
protected final Rectangle rect = new Rectangle();
|
||||||
|
|
||||||
@@ -68,6 +70,7 @@ public class Door extends Wall{
|
|||||||
}
|
}
|
||||||
|
|
||||||
entity.open = !entity.open;
|
entity.open = !entity.open;
|
||||||
|
world.pathfinder.updateSolid(tile);
|
||||||
if(!entity.open){
|
if(!entity.open){
|
||||||
Effects.effect(closefx, tile.drawx(), tile.drawy());
|
Effects.effect(closefx, tile.drawx(), tile.drawy());
|
||||||
}else{
|
}else{
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package io.anuke.mindustry.world.blocks.distribution;
|
package io.anuke.mindustry.world.blocks.distribution;
|
||||||
|
|
||||||
import io.anuke.arc.util.*;
|
import io.anuke.arc.util.Time;
|
||||||
import io.anuke.mindustry.entities.type.TileEntity;
|
import io.anuke.mindustry.entities.type.TileEntity;
|
||||||
|
import io.anuke.mindustry.gen.BufferItem;
|
||||||
import io.anuke.mindustry.type.Item;
|
import io.anuke.mindustry.type.Item;
|
||||||
import io.anuke.mindustry.world.Block;
|
import io.anuke.mindustry.world.*;
|
||||||
import io.anuke.mindustry.world.Tile;
|
|
||||||
import io.anuke.mindustry.world.meta.BlockGroup;
|
import io.anuke.mindustry.world.meta.BlockGroup;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
@@ -19,7 +19,6 @@ public class Junction extends Block{
|
|||||||
super(name);
|
super(name);
|
||||||
update = true;
|
update = true;
|
||||||
solid = true;
|
solid = true;
|
||||||
instantTransfer = true;
|
|
||||||
group = BlockGroup.transportation;
|
group = BlockGroup.transportation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,18 +30,17 @@ public class Junction extends Block{
|
|||||||
@Override
|
@Override
|
||||||
public void update(Tile tile){
|
public void update(Tile tile){
|
||||||
JunctionEntity entity = tile.entity();
|
JunctionEntity entity = tile.entity();
|
||||||
|
DirectionalItemBuffer buffer = entity.buffer;
|
||||||
|
|
||||||
for(int i = 0; i < 4; i++){
|
for(int i = 0; i < 4; i++){
|
||||||
Buffer buffer = entity.buffers[i];
|
if(buffer.indexes[i] > 0){
|
||||||
|
if(buffer.indexes[i] > capacity) buffer.indexes[i] = capacity;
|
||||||
if(buffer.index > 0){
|
long l = buffer.buffers[i][0];
|
||||||
if(buffer.index > buffer.items.length) buffer.index = buffer.items.length;
|
float time = BufferItem.time(l);
|
||||||
long l = buffer.items[0];
|
|
||||||
float time = Float.intBitsToFloat(Pack.leftInt(l));
|
|
||||||
|
|
||||||
if(Time.time() >= time + speed || Time.time() < time){
|
if(Time.time() >= time + speed || Time.time() < time){
|
||||||
|
|
||||||
Item item = content.item(Pack.rightInt(l));
|
Item item = content.item(BufferItem.item(l));
|
||||||
Tile dest = tile.getNearby(i);
|
Tile dest = tile.getNearby(i);
|
||||||
|
|
||||||
//skip blocks that don't want the item, keep waiting until they do
|
//skip blocks that don't want the item, keep waiting until they do
|
||||||
@@ -51,8 +49,8 @@ public class Junction extends Block{
|
|||||||
}
|
}
|
||||||
|
|
||||||
dest.block().handleItem(item, dest, tile);
|
dest.block().handleItem(item, dest, tile);
|
||||||
System.arraycopy(buffer.items, 1, buffer.items, 0, buffer.index - 1);
|
System.arraycopy(buffer.buffers[i], 1, buffer.buffers[i], 0, buffer.indexes[i] - 1);
|
||||||
buffer.index--;
|
buffer.indexes[i] --;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -61,9 +59,8 @@ public class Junction extends Block{
|
|||||||
@Override
|
@Override
|
||||||
public void handleItem(Item item, Tile tile, Tile source){
|
public void handleItem(Item item, Tile tile, Tile source){
|
||||||
JunctionEntity entity = tile.entity();
|
JunctionEntity entity = tile.entity();
|
||||||
long value = Pack.longInt(Float.floatToIntBits(Time.time()), item.id);
|
|
||||||
int relative = source.relativeTo(tile.x, tile.y);
|
int relative = source.relativeTo(tile.x, tile.y);
|
||||||
entity.buffers[relative].add(value);
|
entity.buffer.accept(relative, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -71,7 +68,7 @@ public class Junction extends Block{
|
|||||||
JunctionEntity entity = tile.entity();
|
JunctionEntity entity = tile.entity();
|
||||||
int relative = source.relativeTo(tile.x, tile.y);
|
int relative = source.relativeTo(tile.x, tile.y);
|
||||||
|
|
||||||
if(entity == null || relative == -1 || entity.buffers[relative].full())
|
if(entity == null || relative == -1 || !entity.buffer.accepts(relative))
|
||||||
return false;
|
return false;
|
||||||
Tile to = tile.getNearby(relative);
|
Tile to = tile.getNearby(relative);
|
||||||
return to != null && to.link().entity != null;
|
return to != null && to.link().entity != null;
|
||||||
@@ -83,55 +80,18 @@ public class Junction extends Block{
|
|||||||
}
|
}
|
||||||
|
|
||||||
class JunctionEntity extends TileEntity{
|
class JunctionEntity extends TileEntity{
|
||||||
Buffer[] buffers = {new Buffer(), new Buffer(), new Buffer(), new Buffer()};
|
DirectionalItemBuffer buffer = new DirectionalItemBuffer(capacity, speed);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(DataOutput stream) throws IOException{
|
public void write(DataOutput stream) throws IOException{
|
||||||
super.write(stream);
|
super.write(stream);
|
||||||
for(Buffer b : buffers){
|
buffer.write(stream);
|
||||||
b.write(stream);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void read(DataInput stream, byte revision) throws IOException{
|
public void read(DataInput stream, byte revision) throws IOException{
|
||||||
super.read(stream, revision);
|
super.read(stream, revision);
|
||||||
for(Buffer b : buffers){
|
buffer.read(stream);
|
||||||
b.read(stream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class Buffer{
|
|
||||||
long[] items = new long[capacity];
|
|
||||||
int index;
|
|
||||||
|
|
||||||
void add(long id){
|
|
||||||
if(full()) return;
|
|
||||||
items[index++] = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean full(){
|
|
||||||
return index >= items.length - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void write(DataOutput stream) throws IOException{
|
|
||||||
stream.writeByte((byte)index);
|
|
||||||
stream.writeByte((byte)items.length);
|
|
||||||
for(long l : items){
|
|
||||||
stream.writeLong(l);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void read(DataInput stream) throws IOException{
|
|
||||||
index = stream.readByte();
|
|
||||||
byte length = stream.readByte();
|
|
||||||
for(int i = 0; i < length; i++){
|
|
||||||
long l = stream.readLong();
|
|
||||||
if(i < items.length){
|
|
||||||
items[i] = l;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ public class MassDriver extends Block{
|
|||||||
|
|
||||||
//reload regardless of state
|
//reload regardless of state
|
||||||
if(entity.reload > 0f){
|
if(entity.reload > 0f){
|
||||||
entity.reload = Mathf.clamp(entity.reload - entity.delta() / reloadTime);
|
entity.reload = Mathf.clamp(entity.reload - entity.delta() / reloadTime * entity.power.satisfaction);
|
||||||
}
|
}
|
||||||
|
|
||||||
//cleanup waiting shooters that are not valid
|
//cleanup waiting shooters that are not valid
|
||||||
@@ -114,7 +114,7 @@ public class MassDriver extends Block{
|
|||||||
}
|
}
|
||||||
|
|
||||||
//align to shooter rotation
|
//align to shooter rotation
|
||||||
entity.rotation = Mathf.slerpDelta(entity.rotation, tile.angleTo(entity.currentShooter()), rotateSpeed);
|
entity.rotation = Mathf.slerpDelta(entity.rotation, tile.angleTo(entity.currentShooter()), rotateSpeed * entity.power.satisfaction);
|
||||||
}else if(entity.state == DriverState.shooting){
|
}else if(entity.state == DriverState.shooting){
|
||||||
//if there's nothing to shoot at OR someone wants to shoot at this thing, bail
|
//if there's nothing to shoot at OR someone wants to shoot at this thing, bail
|
||||||
if(!hasLink || !entity.waitingShooters.isEmpty()){
|
if(!hasLink || !entity.waitingShooters.isEmpty()){
|
||||||
@@ -133,7 +133,7 @@ public class MassDriver extends Block{
|
|||||||
other.waitingShooters.add(tile);
|
other.waitingShooters.add(tile);
|
||||||
|
|
||||||
//align to target location
|
//align to target location
|
||||||
entity.rotation = Mathf.slerpDelta(entity.rotation, targetRotation, rotateSpeed);
|
entity.rotation = Mathf.slerpDelta(entity.rotation, targetRotation, rotateSpeed * entity.power.satisfaction);
|
||||||
|
|
||||||
//fire when it's the first in the queue and angles are ready.
|
//fire when it's the first in the queue and angles are ready.
|
||||||
if(other.currentShooter() == tile &&
|
if(other.currentShooter() == tile &&
|
||||||
@@ -214,7 +214,8 @@ public class MassDriver extends Block{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||||
return tile.entity.items.total() < itemCapacity;
|
//mass drivers that ouput only cannot accept items
|
||||||
|
return tile.entity.items.total() < itemCapacity && linkValid(tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,41 +1,56 @@
|
|||||||
package io.anuke.mindustry.world.blocks.distribution;
|
package io.anuke.mindustry.world.blocks.distribution;
|
||||||
|
|
||||||
import io.anuke.arc.math.Mathf;
|
import io.anuke.arc.math.Mathf;
|
||||||
import io.anuke.arc.util.Time;
|
import io.anuke.mindustry.entities.type.TileEntity;
|
||||||
import io.anuke.mindustry.type.Item;
|
import io.anuke.mindustry.type.Item;
|
||||||
import io.anuke.mindustry.world.Edges;
|
import io.anuke.mindustry.world.*;
|
||||||
import io.anuke.mindustry.world.Tile;
|
import io.anuke.mindustry.world.meta.BlockGroup;
|
||||||
|
|
||||||
public class OverflowGate extends Router{
|
import java.io.*;
|
||||||
|
|
||||||
|
public class OverflowGate extends Block{
|
||||||
|
protected int bufferCapacity = 10;
|
||||||
|
protected float speed = 45f;
|
||||||
|
|
||||||
public OverflowGate(String name){
|
public OverflowGate(String name){
|
||||||
super(name);
|
super(name);
|
||||||
hasItems = true;
|
hasItems = true;
|
||||||
speed = 1f;
|
solid = true;
|
||||||
|
update = true;
|
||||||
|
group = BlockGroup.transportation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(Tile tile){
|
public void update(Tile tile){
|
||||||
SplitterEntity entity = tile.entity();
|
OverflowGateEntity entity = tile.entity();
|
||||||
|
|
||||||
if(entity.lastItem == null && entity.items.total() > 0){
|
for(int i = 0; i < 4; i++){
|
||||||
entity.items.clear();
|
Item item = entity.buffer.poll(i);
|
||||||
}
|
if(item != null){
|
||||||
|
Tile other = getTileTarget(tile, item, tile.getNearby(i), true);
|
||||||
if(entity.lastItem != null){
|
if(other != null && other.block().acceptItem(item, other, tile)){
|
||||||
entity.time += 1f / speed * Time.delta();
|
other.block().handleItem(item, other, tile);
|
||||||
Tile target = getTileTarget(tile, entity.lastItem, entity.lastInput, false);
|
entity.buffer.remove(i);
|
||||||
|
}
|
||||||
if(target != null && (entity.time >= 1f)){
|
|
||||||
getTileTarget(tile, entity.lastItem, entity.lastInput, true);
|
|
||||||
target.block().handleItem(entity.lastItem, target, Edges.getFacingEdge(tile, target));
|
|
||||||
entity.items.remove(entity.lastItem, 1);
|
|
||||||
entity.lastItem = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||||
|
OverflowGateEntity entity = tile.entity();
|
||||||
|
return entity.buffer.accepts(tile.relativeTo(source.x, source.y));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleItem(Item item, Tile tile, Tile source){
|
||||||
|
OverflowGateEntity entity = tile.entity();
|
||||||
|
int buffer = tile.relativeTo(source.x, source.y);
|
||||||
|
if(entity.buffer.accepts(buffer)){
|
||||||
|
entity.buffer.accept(buffer, item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Tile getTileTarget(Tile tile, Item item, Tile src, boolean flip){
|
Tile getTileTarget(Tile tile, Item item, Tile src, boolean flip){
|
||||||
int from = tile.relativeTo(src.x, src.y);
|
int from = tile.relativeTo(src.x, src.y);
|
||||||
if(from == -1) return null;
|
if(from == -1) return null;
|
||||||
@@ -70,4 +85,32 @@ public class OverflowGate extends Router{
|
|||||||
|
|
||||||
return to;
|
return to;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TileEntity newEntity(){
|
||||||
|
return new OverflowGateEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class OverflowGateEntity extends TileEntity{
|
||||||
|
DirectionalItemBuffer buffer = new DirectionalItemBuffer(bufferCapacity, speed);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte version(){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(DataOutput stream) throws IOException{
|
||||||
|
super.write(stream);
|
||||||
|
buffer.write(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(DataInput stream, byte revision) throws IOException{
|
||||||
|
super.read(stream, revision);
|
||||||
|
if(revision == 1){
|
||||||
|
buffer.read(stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public class Router extends Block{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(Tile tile){
|
public void update(Tile tile){
|
||||||
SplitterEntity entity = tile.entity();
|
RouterEntity entity = tile.entity();
|
||||||
|
|
||||||
if(entity.lastItem == null && entity.items.total() > 0){
|
if(entity.lastItem == null && entity.items.total() > 0){
|
||||||
entity.items.clear();
|
entity.items.clear();
|
||||||
@@ -42,14 +42,14 @@ public class Router extends Block{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||||
SplitterEntity entity = tile.entity();
|
RouterEntity entity = tile.entity();
|
||||||
|
|
||||||
return tile.getTeam() == source.getTeam() && entity.lastItem == null && entity.items.total() == 0;
|
return tile.getTeam() == source.getTeam() && entity.lastItem == null && entity.items.total() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleItem(Item item, Tile tile, Tile source){
|
public void handleItem(Item item, Tile tile, Tile source){
|
||||||
SplitterEntity entity = tile.entity();
|
RouterEntity entity = tile.entity();
|
||||||
entity.items.add(item, 1);
|
entity.items.add(item, 1);
|
||||||
entity.lastItem = item;
|
entity.lastItem = item;
|
||||||
entity.time = 0f;
|
entity.time = 0f;
|
||||||
@@ -72,7 +72,7 @@ public class Router extends Block{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int removeStack(Tile tile, Item item, int amount){
|
public int removeStack(Tile tile, Item item, int amount){
|
||||||
SplitterEntity entity = tile.entity();
|
RouterEntity entity = tile.entity();
|
||||||
int result = super.removeStack(tile, item, amount);
|
int result = super.removeStack(tile, item, amount);
|
||||||
if(result != 0 && item == entity.lastItem){
|
if(result != 0 && item == entity.lastItem){
|
||||||
entity.lastItem = null;
|
entity.lastItem = null;
|
||||||
@@ -82,10 +82,10 @@ public class Router extends Block{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TileEntity newEntity(){
|
public TileEntity newEntity(){
|
||||||
return new SplitterEntity();
|
return new RouterEntity();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SplitterEntity extends TileEntity{
|
public class RouterEntity extends TileEntity{
|
||||||
Item lastItem;
|
Item lastItem;
|
||||||
Tile lastInput;
|
Tile lastInput;
|
||||||
float time;
|
float time;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package io.anuke.mindustry.world.blocks.distribution;
|
package io.anuke.mindustry.world.blocks.distribution;
|
||||||
|
|
||||||
import io.anuke.annotations.Annotations.Loc;
|
import io.anuke.annotations.Annotations.*;
|
||||||
import io.anuke.annotations.Annotations.Remote;
|
|
||||||
import io.anuke.arc.Core;
|
import io.anuke.arc.Core;
|
||||||
import io.anuke.arc.graphics.g2d.Draw;
|
import io.anuke.arc.graphics.g2d.Draw;
|
||||||
import io.anuke.arc.math.Mathf;
|
import io.anuke.arc.math.Mathf;
|
||||||
@@ -10,8 +9,7 @@ import io.anuke.mindustry.entities.type.Player;
|
|||||||
import io.anuke.mindustry.entities.type.TileEntity;
|
import io.anuke.mindustry.entities.type.TileEntity;
|
||||||
import io.anuke.mindustry.gen.Call;
|
import io.anuke.mindustry.gen.Call;
|
||||||
import io.anuke.mindustry.type.Item;
|
import io.anuke.mindustry.type.Item;
|
||||||
import io.anuke.mindustry.world.Block;
|
import io.anuke.mindustry.world.*;
|
||||||
import io.anuke.mindustry.world.Tile;
|
|
||||||
import io.anuke.mindustry.world.blocks.ItemSelection;
|
import io.anuke.mindustry.world.blocks.ItemSelection;
|
||||||
import io.anuke.mindustry.world.meta.BlockGroup;
|
import io.anuke.mindustry.world.meta.BlockGroup;
|
||||||
|
|
||||||
@@ -22,11 +20,13 @@ import static io.anuke.mindustry.Vars.content;
|
|||||||
public class Sorter extends Block{
|
public class Sorter extends Block{
|
||||||
private static Item lastItem;
|
private static Item lastItem;
|
||||||
|
|
||||||
|
protected int bufferCapacity = 20;
|
||||||
|
protected float speed = 45f;
|
||||||
|
|
||||||
public Sorter(String name){
|
public Sorter(String name){
|
||||||
super(name);
|
super(name);
|
||||||
update = true;
|
update = true;
|
||||||
solid = true;
|
solid = true;
|
||||||
instantTransfer = true;
|
|
||||||
group = BlockGroup.transportation;
|
group = BlockGroup.transportation;
|
||||||
configurable = true;
|
configurable = true;
|
||||||
}
|
}
|
||||||
@@ -57,24 +57,42 @@ public class Sorter extends Block{
|
|||||||
if(entity.sortItem == null) return;
|
if(entity.sortItem == null) return;
|
||||||
|
|
||||||
Draw.color(entity.sortItem.color);
|
Draw.color(entity.sortItem.color);
|
||||||
Draw.rect("blank", tile.worldx(), tile.worldy(), 4f, 4f);
|
Draw.rect("center", tile.worldx(), tile.worldy());
|
||||||
Draw.color();
|
Draw.color();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
public void update(Tile tile){
|
||||||
Tile to = getTileTarget(item, tile, source, false);
|
SorterEntity entity = tile.entity();
|
||||||
|
|
||||||
return to != null && to.block().acceptItem(item, to, tile);
|
for(int i = 0; i < 4; i++){
|
||||||
|
Item item = entity.buffer.poll(i);
|
||||||
|
if(item != null){
|
||||||
|
Tile other = getTileTarget(item, tile, tile.getNearby(i), true);
|
||||||
|
if(other != null && other.block().acceptItem(item, other, tile)){
|
||||||
|
other.block().handleItem(item, other, tile);
|
||||||
|
entity.buffer.remove(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||||
|
SorterEntity entity = tile.entity();
|
||||||
|
return entity.buffer.accepts(tile.relativeTo(source.x, source.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleItem(Item item, Tile tile, Tile source){
|
public void handleItem(Item item, Tile tile, Tile source){
|
||||||
Tile to = getTileTarget(item, tile, source, true);
|
SorterEntity entity = tile.entity();
|
||||||
|
int buffer = tile.relativeTo(source.x, source.y);
|
||||||
to.block().handleItem(item, to, tile);
|
if(entity.buffer.accepts(buffer)){
|
||||||
|
entity.buffer.accept(buffer, item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
Tile getTileTarget(Item item, Tile dest, Tile source, boolean flip){
|
Tile getTileTarget(Item item, Tile dest, Tile source, boolean flip){
|
||||||
SorterEntity entity = dest.entity();
|
SorterEntity entity = dest.entity();
|
||||||
|
|
||||||
@@ -87,10 +105,8 @@ public class Sorter extends Block{
|
|||||||
}else{
|
}else{
|
||||||
Tile a = dest.getNearby(Mathf.mod(dir - 1, 4));
|
Tile a = dest.getNearby(Mathf.mod(dir - 1, 4));
|
||||||
Tile b = dest.getNearby(Mathf.mod(dir + 1, 4));
|
Tile b = dest.getNearby(Mathf.mod(dir + 1, 4));
|
||||||
boolean ac = a != null && !(a.block().instantTransfer && source.block().instantTransfer) &&
|
boolean ac = a != null && a.block().acceptItem(item, a, dest);
|
||||||
a.block().acceptItem(item, a, dest);
|
boolean bc = b != null && b.block().acceptItem(item, b, dest);
|
||||||
boolean bc = b != null && !(b.block().instantTransfer && source.block().instantTransfer) &&
|
|
||||||
b.block().acceptItem(item, b, dest);
|
|
||||||
|
|
||||||
if(ac && !bc){
|
if(ac && !bc){
|
||||||
to = a;
|
to = a;
|
||||||
@@ -101,12 +117,10 @@ public class Sorter extends Block{
|
|||||||
}else{
|
}else{
|
||||||
if(dest.rotation() == 0){
|
if(dest.rotation() == 0){
|
||||||
to = a;
|
to = a;
|
||||||
if(flip)
|
if(flip) dest.rotation((byte)1);
|
||||||
dest.rotation((byte)1);
|
|
||||||
}else{
|
}else{
|
||||||
to = b;
|
to = b;
|
||||||
if(flip)
|
if(flip) dest.rotation((byte)0);
|
||||||
dest.rotation((byte)0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -128,19 +142,29 @@ public class Sorter extends Block{
|
|||||||
return new SorterEntity();
|
return new SorterEntity();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class SorterEntity extends TileEntity{
|
public class SorterEntity extends TileEntity{
|
||||||
public Item sortItem;
|
DirectionalItemBuffer buffer = new DirectionalItemBuffer(bufferCapacity, speed);
|
||||||
|
Item sortItem;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte version(){
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void write(DataOutput stream) throws IOException{
|
public void write(DataOutput stream) throws IOException{
|
||||||
super.write(stream);
|
super.write(stream);
|
||||||
stream.writeShort(sortItem == null ? -1 : sortItem.id);
|
stream.writeShort(sortItem == null ? -1 : sortItem.id);
|
||||||
|
buffer.write(stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void read(DataInput stream, byte revision) throws IOException{
|
public void read(DataInput stream, byte revision) throws IOException{
|
||||||
super.read(stream, revision);
|
super.read(stream, revision);
|
||||||
sortItem = content.item(stream.readShort());
|
sortItem = content.item(stream.readShort());
|
||||||
|
if(revision == 1){
|
||||||
|
buffer.read(stream);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,46 @@
|
|||||||
package io.anuke.mindustry.world.blocks.sandbox;
|
package io.anuke.mindustry.world.blocks.sandbox;
|
||||||
|
|
||||||
|
import io.anuke.annotations.Annotations.Loc;
|
||||||
|
import io.anuke.annotations.Annotations.Remote;
|
||||||
|
import io.anuke.arc.Core;
|
||||||
|
import io.anuke.arc.graphics.g2d.Draw;
|
||||||
|
import io.anuke.arc.scene.ui.layout.Table;
|
||||||
|
import io.anuke.mindustry.entities.type.Player;
|
||||||
|
import io.anuke.mindustry.entities.type.TileEntity;
|
||||||
|
import io.anuke.mindustry.gen.Call;
|
||||||
import io.anuke.mindustry.type.Item;
|
import io.anuke.mindustry.type.Item;
|
||||||
|
import io.anuke.mindustry.world.Block;
|
||||||
import io.anuke.mindustry.world.Tile;
|
import io.anuke.mindustry.world.Tile;
|
||||||
import io.anuke.mindustry.world.blocks.distribution.Sorter;
|
import io.anuke.mindustry.world.blocks.ItemSelection;
|
||||||
|
import io.anuke.mindustry.world.meta.BlockGroup;
|
||||||
|
|
||||||
public class ItemSource extends Sorter{
|
import java.io.*;
|
||||||
|
|
||||||
|
import static io.anuke.mindustry.Vars.content;
|
||||||
|
|
||||||
|
public class ItemSource extends Block{
|
||||||
|
private static Item lastItem;
|
||||||
|
|
||||||
public ItemSource(String name){
|
public ItemSource(String name){
|
||||||
super(name);
|
super(name);
|
||||||
hasItems = true;
|
hasItems = true;
|
||||||
update = true;
|
update = true;
|
||||||
solid = true;
|
solid = true;
|
||||||
|
group = BlockGroup.transportation;
|
||||||
|
configurable = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Remote(targets = Loc.both, called = Loc.both, forward = true)
|
||||||
|
public static void setItemSourceItem(Player player, Tile tile, Item item){
|
||||||
|
ItemSourceEntity entity = tile.entity();
|
||||||
|
if(entity != null){
|
||||||
|
entity.outputItem = item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void playerPlaced(Tile tile){
|
||||||
|
Core.app.post(() -> Call.setItemSourceItem(null, tile, lastItem));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -25,17 +55,59 @@ public class ItemSource extends Sorter{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(Tile tile){
|
public void draw(Tile tile){
|
||||||
SorterEntity entity = tile.entity();
|
super.draw(tile);
|
||||||
if(entity.sortItem == null) return;
|
|
||||||
|
|
||||||
entity.items.set(entity.sortItem, 1);
|
ItemSourceEntity entity = tile.entity();
|
||||||
tryDump(tile, entity.sortItem);
|
if(entity.outputItem == null) return;
|
||||||
entity.items.set(entity.sortItem, 0);
|
|
||||||
|
Draw.color(entity.outputItem.color);
|
||||||
|
Draw.rect("center", tile.worldx(), tile.worldy());
|
||||||
|
Draw.color();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void update(Tile tile){
|
||||||
|
ItemSourceEntity entity = tile.entity();
|
||||||
|
if(entity.outputItem == null) return;
|
||||||
|
|
||||||
|
entity.items.set(entity.outputItem, 1);
|
||||||
|
tryDump(tile, entity.outputItem);
|
||||||
|
entity.items.set(entity.outputItem, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void buildTable(Tile tile, Table table){
|
||||||
|
ItemSourceEntity entity = tile.entity();
|
||||||
|
ItemSelection.buildItemTable(table, () -> entity.outputItem, item -> {
|
||||||
|
lastItem = item;
|
||||||
|
Call.setItemSourceItem(null, tile, item);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean acceptItem(Item item, Tile tile, Tile source){
|
public boolean acceptItem(Item item, Tile tile, Tile source){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TileEntity newEntity(){
|
||||||
|
return new ItemSourceEntity();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ItemSourceEntity extends TileEntity{
|
||||||
|
Item outputItem;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(DataOutput stream) throws IOException{
|
||||||
|
super.write(stream);
|
||||||
|
stream.writeShort(outputItem == null ? -1 : outputItem.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void read(DataInput stream, byte revision) throws IOException{
|
||||||
|
super.read(stream, revision);
|
||||||
|
outputItem = content.item(stream.readShort());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ public class LiquidSource extends Block{
|
|||||||
|
|
||||||
if(entity.source != null){
|
if(entity.source != null){
|
||||||
Draw.color(entity.source.color);
|
Draw.color(entity.source.color);
|
||||||
Draw.rect("blank", tile.worldx(), tile.worldy(), 4f, 4f);
|
Draw.rect("center", tile.worldx(), tile.worldy());
|
||||||
Draw.color();
|
Draw.color();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,8 +81,8 @@ public class MechPad extends Block{
|
|||||||
|
|
||||||
protected static boolean checkValidTap(Tile tile, Player player){
|
protected static boolean checkValidTap(Tile tile, Player player){
|
||||||
MechFactoryEntity entity = tile.entity();
|
MechFactoryEntity entity = tile.entity();
|
||||||
return Math.abs(player.x - tile.drawx()) <= tile.block().size * tilesize / 2f &&
|
return Math.abs(player.x - tile.drawx()) <= tile.block().size * tilesize &&
|
||||||
Math.abs(player.y - tile.drawy()) <= tile.block().size * tilesize / 2f && entity.cons.valid() && entity.player == null;
|
Math.abs(player.y - tile.drawy()) <= tile.block().size * tilesize && entity.cons.valid() && entity.player == null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,14 +1,11 @@
|
|||||||
package io.anuke.mindustry.desktop;
|
package io.anuke.mindustry.desktop;
|
||||||
|
|
||||||
import club.minnced.discord.rpc.DiscordEventHandlers;
|
import club.minnced.discord.rpc.*;
|
||||||
import club.minnced.discord.rpc.DiscordRPC;
|
|
||||||
import club.minnced.discord.rpc.DiscordRichPresence;
|
|
||||||
import io.anuke.arc.collection.Array;
|
import io.anuke.arc.collection.Array;
|
||||||
import io.anuke.arc.files.FileHandle;
|
import io.anuke.arc.files.FileHandle;
|
||||||
import io.anuke.arc.function.Consumer;
|
import io.anuke.arc.function.Consumer;
|
||||||
import io.anuke.arc.util.Log;
|
import io.anuke.arc.function.Predicate;
|
||||||
import io.anuke.arc.util.OS;
|
import io.anuke.arc.util.*;
|
||||||
import io.anuke.arc.util.Strings;
|
|
||||||
import io.anuke.arc.util.serialization.Base64Coder;
|
import io.anuke.arc.util.serialization.Base64Coder;
|
||||||
import io.anuke.mindustry.core.GameState.State;
|
import io.anuke.mindustry.core.GameState.State;
|
||||||
import io.anuke.mindustry.core.Platform;
|
import io.anuke.mindustry.core.Platform;
|
||||||
@@ -69,8 +66,8 @@ public class DesktopPlatform extends Platform{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void showFileChooser(String text, String content, Consumer<FileHandle> cons, boolean open, String filter){
|
public void showFileChooser(String text, String content, Consumer<FileHandle> cons, boolean open, Predicate<String> filetype){
|
||||||
new FileChooser(text, file -> file.extension().equalsIgnoreCase(filter), open, cons).show();
|
new FileChooser(text, file -> filetype.test(file.extension().toLowerCase()), open, cons).show();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,5 +1,5 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ public class IOSLauncher extends IOSApplication.Delegate{
|
|||||||
SaveSlot slot = control.saves.importSave(file);
|
SaveSlot slot = control.saves.importSave(file);
|
||||||
ui.load.runLoadSave(slot);
|
ui.load.runLoadSave(slot);
|
||||||
}catch(IOException e){
|
}catch(IOException e){
|
||||||
ui.showError(Core.bundle.format("save.import.fail", Strings.parseException(e, false)));
|
ui.showError(Core.bundle.format("save.import.fail", Strings.parseException(e, true)));
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
ui.showError("save.import.invalid");
|
ui.showError("save.import.invalid");
|
||||||
|
|||||||