Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -40,6 +40,7 @@ public abstract class ClientLauncher extends ApplicationCore implements Platform
|
||||
batch = new SpriteBatch();
|
||||
assets = new AssetManager();
|
||||
assets.setLoader(Texture.class, "." + mapExtension, new MapPreviewLoader());
|
||||
assets.load("sprites/error.png", Texture.class);
|
||||
atlas = TextureAtlas.blankAtlas();
|
||||
Vars.net = new Net(platform.getNet());
|
||||
|
||||
|
||||
@@ -122,8 +122,6 @@ public class Vars implements Loadable{
|
||||
public static FileHandle saveDirectory;
|
||||
/** data subdirectory used for plugins */
|
||||
public static FileHandle pluginDirectory;
|
||||
/** old map file extension, for conversion */
|
||||
public static final String oldMapExtension = "mmap";
|
||||
/** map file extension */
|
||||
public static final String mapExtension = "msav";
|
||||
/** save file extension */
|
||||
@@ -139,7 +137,7 @@ public class Vars implements Loadable{
|
||||
public static EntityCollisions collisions;
|
||||
public static DefaultWaves defaultWaves;
|
||||
public static LoopControl loops;
|
||||
public static Platform platform;
|
||||
public static Platform platform = new Platform(){};
|
||||
public static Plugins plugins;
|
||||
|
||||
public static World world;
|
||||
|
||||
@@ -46,6 +46,7 @@ public class StatusEffects implements ContentList{
|
||||
if(unit.getTeam() == waveTeam){
|
||||
Events.fire(Trigger.shock);
|
||||
}
|
||||
result.set(this, time);
|
||||
}));
|
||||
opposite(() -> burning);
|
||||
}};
|
||||
|
||||
@@ -371,11 +371,13 @@ public class Control implements ApplicationListener, Loadable{
|
||||
|
||||
@Override
|
||||
public void update(){
|
||||
//TODO find out why this happens on Android
|
||||
if(assets == null) return;
|
||||
|
||||
saves.update();
|
||||
|
||||
//update and load any requested assets
|
||||
if(assets != null){
|
||||
assets.update();
|
||||
}
|
||||
assets.update();
|
||||
|
||||
input.updateController();
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.anuke.mindustry.core;
|
||||
|
||||
import io.anuke.arc.*;
|
||||
import io.anuke.arc.Input.*;
|
||||
import io.anuke.arc.collection.*;
|
||||
import io.anuke.arc.files.*;
|
||||
import io.anuke.arc.function.*;
|
||||
import io.anuke.arc.math.*;
|
||||
@@ -25,6 +26,14 @@ public interface Platform{
|
||||
/** Steam: Share a map on the workshop.*/
|
||||
default void publishMap(Map map){}
|
||||
|
||||
/** Steam: Return external workshop maps to be loaded.*/
|
||||
default Array<FileHandle> getExternalMaps(){
|
||||
return Array.with();
|
||||
}
|
||||
|
||||
/** Steam: View a map listing on the workshop.*/
|
||||
default void viewMapListing(Map map){}
|
||||
|
||||
/** Steam: Open workshop for maps.*/
|
||||
default void openWorkshop(){}
|
||||
|
||||
|
||||
@@ -325,8 +325,9 @@ public class UI implements ApplicationListener, Loadable{
|
||||
cont.row();
|
||||
cont.addImage().width(300f).pad(2).height(4f).color(Color.scarlet);
|
||||
cont.row();
|
||||
cont.add(text).pad(2f).growX().wrap();
|
||||
buttons.addButton("$ok", this::hide).size(120, 50).pad(4);
|
||||
cont.add(text).pad(2f).growX().wrap().get().setAlignment(Align.center);
|
||||
cont.row();
|
||||
cont.addButton("$ok", this::hide).size(120, 50).pad(4);
|
||||
}}.show();
|
||||
}
|
||||
|
||||
|
||||
@@ -154,10 +154,21 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
||||
if(steam){
|
||||
menu.cont.addImageTextButton("$editor.publish.workshop", Icon.linkSmall, () -> {
|
||||
Map map = save();
|
||||
if(map != null){
|
||||
platform.publishMap(map);
|
||||
|
||||
if(map == null) return;
|
||||
|
||||
if(map.tags.get("description", "").length() < 4){
|
||||
ui.showErrorMessage("$editor.nodescription");
|
||||
return;
|
||||
}
|
||||
}).padTop(-3).size(swidth * 2f + 10, 60f);
|
||||
|
||||
if(!Gamemode.survival.valid(map)){
|
||||
ui.showErrorMessage("$map.nospawn");
|
||||
return;
|
||||
}
|
||||
|
||||
platform.publishMap(map);
|
||||
}).padTop(-3).size(swidth * 2f + 10, 60f).update(b -> b.setText(editor.getTags().containsKey("steamid") ? "$view.workshop" : "$editor.publish.workshop"));
|
||||
|
||||
menu.cont.row();
|
||||
}
|
||||
@@ -276,7 +287,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
||||
});
|
||||
}
|
||||
|
||||
private Map save(){
|
||||
public Map save(){
|
||||
String name = editor.getTags().get("name", "").trim();
|
||||
editor.getTags().put("rules", JsonIO.write(state.rules));
|
||||
editor.getTags().remove("width");
|
||||
|
||||
@@ -54,7 +54,7 @@ public class MapLoadDialog extends FloatingDialog{
|
||||
for(Map map : maps.all()){
|
||||
|
||||
TextButton button = new TextButton(map.name(), Styles.togglet);
|
||||
button.add(new BorderImage(map.texture, 2f).setScaling(Scaling.fit)).size(16 * 4f);
|
||||
button.add(new BorderImage(map.safeTexture(), 2f).setScaling(Scaling.fit)).size(16 * 4f);
|
||||
button.getCells().reverse();
|
||||
button.clicked(() -> selected = map);
|
||||
button.getLabelCell().grow().left().padLeft(5f);
|
||||
|
||||
@@ -18,6 +18,8 @@ public class EntityGroup<T extends Entity>{
|
||||
private final Array<T> entityArray = new Array<>(false, 32);
|
||||
private final Array<T> entitiesToRemove = new Array<>(false, 32);
|
||||
private final Array<T> entitiesToAdd = new Array<>(false, 32);
|
||||
private final Array<T> intersectArray = new Array<>();
|
||||
private final Rectangle intersectRect = new Rectangle();
|
||||
private IntMap<T> map;
|
||||
private QuadTree tree;
|
||||
private Consumer<T> removeListener;
|
||||
@@ -161,6 +163,15 @@ public class EntityGroup<T extends Entity>{
|
||||
tree().getIntersect(out, x, y, width, height);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Array<T> intersect(float x, float y, float width, float height){
|
||||
intersectArray.clear();
|
||||
//don't waste time for empty groups
|
||||
if(isEmpty()) return intersectArray;
|
||||
tree().getIntersect(intersectArray, intersectRect.set(x, y, width, height));
|
||||
return intersectArray;
|
||||
}
|
||||
|
||||
public QuadTree tree(){
|
||||
if(!useTree) throw new RuntimeException("This group does not support quadtrees! Enable quadtrees when creating it.");
|
||||
return tree;
|
||||
|
||||
@@ -47,7 +47,7 @@ public class Lightning extends TimedEntity implements DrawTrait, TimeTrait{
|
||||
}
|
||||
|
||||
/** Do not invoke! */
|
||||
@Remote(called = Loc.server)
|
||||
@Remote(called = Loc.server, unreliable = true)
|
||||
public static void createLighting(int seed, Team team, Color color, float damage, float x, float y, float rotation, int length){
|
||||
|
||||
Lightning l = Pools.obtain(Lightning.class, Lightning::new);
|
||||
|
||||
@@ -16,6 +16,7 @@ import io.anuke.mindustry.game.*;
|
||||
import io.anuke.mindustry.gen.*;
|
||||
import io.anuke.mindustry.type.*;
|
||||
import io.anuke.mindustry.world.*;
|
||||
import io.anuke.mindustry.world.blocks.*;
|
||||
import io.anuke.mindustry.world.blocks.defense.DeflectorWall.*;
|
||||
import io.anuke.mindustry.world.blocks.units.CommandCenter.*;
|
||||
import io.anuke.mindustry.world.blocks.units.UnitFactory.*;
|
||||
@@ -273,7 +274,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
||||
return;
|
||||
}
|
||||
|
||||
if(!isFlying() && (world.tileWorld(x, y) != null && world.tileWorld(x, y).solid())){
|
||||
if(!isFlying() && (world.tileWorld(x, y) != null && !(world.tileWorld(x, y).block() instanceof BuildBlock) && world.tileWorld(x, y).solid())){
|
||||
kill();
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.anuke.mindustry.entities.type;
|
||||
|
||||
import io.anuke.annotations.Annotations.*;
|
||||
import io.anuke.arc.*;
|
||||
import io.anuke.arc.collection.*;
|
||||
import io.anuke.arc.graphics.*;
|
||||
import io.anuke.arc.graphics.g2d.*;
|
||||
import io.anuke.arc.math.*;
|
||||
@@ -212,15 +213,25 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
||||
float radScl = 1.5f;
|
||||
float fsize = getSize() / radScl;
|
||||
moveVector.setZero();
|
||||
float cx = x - fsize/2f, cy = y - fsize/2f;
|
||||
|
||||
Units.nearby(x - fsize/2f, y - fsize/2f, fsize, fsize, en -> {
|
||||
if(en == this || en.isFlying() != isFlying()) return;
|
||||
for(Team team : Team.all){
|
||||
avoid(unitGroups[team.ordinal()].intersect(cx, cy, fsize, fsize));
|
||||
}
|
||||
|
||||
avoid(playerGroup.intersect(cx, cy, fsize, fsize));
|
||||
velocity.add(moveVector.x / mass() * Time.delta(), moveVector.y / mass() * Time.delta());
|
||||
}
|
||||
|
||||
private void avoid(Array<? extends Unit> arr){
|
||||
float radScl = 1.5f;
|
||||
|
||||
for(Unit en : arr){
|
||||
if(en.isFlying() != isFlying()) continue;
|
||||
float dst = dst(en);
|
||||
float scl = Mathf.clamp(1f - dst / (getSize()/(radScl*2f) + en.getSize()/(radScl*2f)));
|
||||
moveVector.add(Tmp.v1.set((x - en.x) * scl, (y - en.y) * scl).limit(0.4f));
|
||||
});
|
||||
|
||||
velocity.add(moveVector.x / mass() * Time.delta(), moveVector.y / mass() * Time.delta());
|
||||
}
|
||||
}
|
||||
|
||||
public @Nullable TileEntity getClosestCore(){
|
||||
|
||||
@@ -32,12 +32,12 @@ public class Statuses implements Saveable{
|
||||
if(statuses.size > 0){
|
||||
//check for opposite effects
|
||||
for(StatusEntry entry : statuses){
|
||||
if(entry.effect == null) continue;
|
||||
//extend effect
|
||||
if(entry.effect == effect){
|
||||
entry.time = Math.max(entry.time, duration);
|
||||
return;
|
||||
}else if(entry.effect.reactsWith(effect)){ //find opposite
|
||||
globalResult.effect = entry.effect;
|
||||
entry.effect.getTransition(unit, effect, entry.time, duration, globalResult);
|
||||
entry.time = globalResult.time;
|
||||
|
||||
@@ -84,10 +84,6 @@ public class Statuses implements Saveable{
|
||||
removals.clear();
|
||||
|
||||
for(StatusEntry entry : statuses){
|
||||
if(entry.effect == null){
|
||||
removals.add(entry);
|
||||
continue;
|
||||
}
|
||||
entry.time = Math.max(entry.time - Time.delta(), 0);
|
||||
applied.set(entry.effect.id);
|
||||
|
||||
|
||||
@@ -187,7 +187,7 @@ public class Tutorial{
|
||||
}
|
||||
},;
|
||||
|
||||
protected final String line = Core.bundle.has("tutorial." + name() + ".mobile") && mobile ? "tutorial." + name() + ".mobile" : "tutorial." + name();
|
||||
protected String line = "";
|
||||
protected final Function<String, String> text;
|
||||
protected Array<String> sentences;
|
||||
protected final BooleanProvider done;
|
||||
@@ -203,7 +203,10 @@ public class Tutorial{
|
||||
|
||||
/** displayed tutorial stage text.*/
|
||||
public String text(){
|
||||
if(sentences == null) this.sentences = Array.select(Core.bundle.get(line).split("\n"), s -> !s.isEmpty());
|
||||
if(sentences == null){
|
||||
this.line = Core.bundle.has("tutorial." + name() + ".mobile") && mobile ? "tutorial." + name() + ".mobile" : "tutorial." + name();
|
||||
this.sentences = Array.select(Core.bundle.get(line).split("\n"), s -> !s.isEmpty());
|
||||
}
|
||||
String line = sentences.get(control.tutorial.sentence);
|
||||
return line.contains("{") ? text.get(line) : line;
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ public abstract class InputHandler implements InputProcessor{
|
||||
|
||||
@Remote(targets = Loc.both, forward = true, called = Loc.server)
|
||||
public static void transferInventory(Player player, Tile tile){
|
||||
if(!player.timer.get(Player.timerTransfer, 40)) return;
|
||||
if(player == null || player.timer == null || !player.timer.get(Player.timerTransfer, 40)) return;
|
||||
if(net.server() && (player.item().amount <= 0 || player.isTransferring|| !tile.interactable(player.getTeam()))){
|
||||
throw new ValidateException(player, "Player cannot transfer an item.");
|
||||
}
|
||||
|
||||
@@ -67,33 +67,7 @@ public class MobileInput extends InputHandler implements GestureListener{
|
||||
|
||||
public MobileInput(){
|
||||
Events.on(ClientLoadEvent.class, e -> {
|
||||
GestureDetector dec = new GestureDetector(20, 0.5f, 0.4f, 0.15f, this){
|
||||
boolean clearMouse = false;
|
||||
|
||||
@Override
|
||||
public boolean touchDown(int x, int y, int pointer, KeyCode button){
|
||||
if(Core.scene.hasMouse(x, y)){
|
||||
clearMouse = true;
|
||||
return false;
|
||||
}
|
||||
return super.touchDown(x, y, pointer, button);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean touchDragged(int x, int y, int pointer){
|
||||
if(!clearMouse){
|
||||
return super.touchDragged(x, y, pointer);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean touchUp(int x, int y, int pointer, KeyCode button){
|
||||
clearMouse = false;
|
||||
return super.touchUp(x, y, pointer, button);
|
||||
}
|
||||
};
|
||||
Core.input.getInputProcessors().insert(0, dec);
|
||||
Core.input.getInputProcessors().add(new GestureDetector(20, 0.5f, 0.4f, 0.15f, this));
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,8 @@ public class Map implements Comparable<Map>{
|
||||
public final FileHandle file;
|
||||
/** Format version. */
|
||||
public final int version;
|
||||
/** Whether this map is managed, e.g. downloaded from the Steam workshop.*/
|
||||
public boolean workshop;
|
||||
/** Map width/height, shorts. */
|
||||
public int width, height;
|
||||
/** Preview texture. */
|
||||
@@ -57,8 +59,12 @@ public class Map implements Comparable<Map>{
|
||||
return Core.settings.getInt("hiscore" + file.nameWithoutExtension(), 0);
|
||||
}
|
||||
|
||||
public Texture safeTexture(){
|
||||
return texture == null ? Core.assets.get("sprites/error.png") : texture;
|
||||
}
|
||||
|
||||
public FileHandle previewFile(){
|
||||
return Vars.mapPreviewDirectory.child(file.nameWithoutExtension() + ".png");
|
||||
return Vars.mapPreviewDirectory.child((workshop ? file.parent().name() : file.nameWithoutExtension()) + ".png");
|
||||
}
|
||||
|
||||
public FileHandle cacheFile(){
|
||||
@@ -127,6 +133,8 @@ public class Map implements Comparable<Map>{
|
||||
|
||||
@Override
|
||||
public int compareTo(Map map){
|
||||
int work = -Boolean.compare(workshop, map.workshop);
|
||||
if(work != 0) return work;
|
||||
int type = -Boolean.compare(custom, map.custom);
|
||||
if(type != 0) return type;
|
||||
int modes = Boolean.compare(Gamemode.pvp.valid(this), Gamemode.pvp.valid(map));
|
||||
|
||||
@@ -6,6 +6,7 @@ import io.anuke.arc.assets.loaders.resolvers.*;
|
||||
import io.anuke.arc.collection.*;
|
||||
import io.anuke.arc.files.*;
|
||||
import io.anuke.arc.graphics.*;
|
||||
import io.anuke.arc.util.*;
|
||||
import io.anuke.mindustry.*;
|
||||
import io.anuke.mindustry.game.*;
|
||||
|
||||
@@ -20,7 +21,7 @@ public class MapPreviewLoader extends TextureLoader{
|
||||
try{
|
||||
super.loadAsync(manager, fileName, file.sibling(file.nameWithoutExtension()), parameter);
|
||||
}catch(Exception e){
|
||||
e.printStackTrace();
|
||||
Log.err(e);
|
||||
MapPreviewParameter param = (MapPreviewParameter)parameter;
|
||||
Vars.maps.queueNewPreview(param.map);
|
||||
}
|
||||
@@ -31,11 +32,11 @@ public class MapPreviewLoader extends TextureLoader{
|
||||
try{
|
||||
return super.loadSync(manager, fileName, file, parameter);
|
||||
}catch(Throwable e){
|
||||
e.printStackTrace();
|
||||
Log.err(e);
|
||||
try{
|
||||
return new Texture(file);
|
||||
}catch(Throwable e2){
|
||||
e2.printStackTrace();
|
||||
Log.err(e2);
|
||||
return new Texture("sprites/error.png");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,6 +81,7 @@ public class Maps{
|
||||
|
||||
/** Load all maps. Should be called at application start. */
|
||||
public void load(){
|
||||
//defaults; must work
|
||||
try{
|
||||
for(String name : defaultMapNames){
|
||||
FileHandle file = Core.files.internal("maps/" + name + "." + mapExtension);
|
||||
@@ -90,7 +91,27 @@ public class Maps{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
loadCustomMaps();
|
||||
//custom
|
||||
for(FileHandle file : customMapDirectory.list()){
|
||||
try{
|
||||
if(file.extension().equalsIgnoreCase(mapExtension)){
|
||||
loadMap(file, true);
|
||||
}
|
||||
}catch(Exception e){
|
||||
Log.err("Failed to load custom map file '{0}'!", file);
|
||||
Log.err(e);
|
||||
}
|
||||
}
|
||||
|
||||
//workshop
|
||||
for(FileHandle file : platform.getExternalMaps()){
|
||||
try{
|
||||
loadMap(file, false).workshop = true;
|
||||
}catch(Exception e){
|
||||
Log.err("Failed to load workshop map file '{0}'!", file);
|
||||
Log.err(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void reload(){
|
||||
@@ -174,14 +195,6 @@ public class Maps{
|
||||
}
|
||||
}
|
||||
|
||||
/** 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. */
|
||||
public void importMap(FileHandle file) throws IOException{
|
||||
FileHandle dest = findFile();
|
||||
@@ -203,7 +216,6 @@ public class Maps{
|
||||
if(error[0] != null){
|
||||
throw new IOException(error[0]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Attempts to run the following code;
|
||||
@@ -314,7 +326,7 @@ public class Maps{
|
||||
for(Map map : maps){
|
||||
//try to load preview
|
||||
if(map.previewFile().exists()){
|
||||
//this may fail, but calls createNewPreview
|
||||
//this may fail, but calls queueNewPreview
|
||||
Core.assets.load(new AssetDescriptor<>(map.previewFile().path() + "." + mapExtension, Texture.class, new MapPreviewParameter(map))).loaded = t -> map.texture = (Texture)t;
|
||||
|
||||
try{
|
||||
@@ -332,7 +344,7 @@ public class Maps{
|
||||
private void createAllPreviews(){
|
||||
Core.app.post(() -> {
|
||||
for(Map map : previewList){
|
||||
createNewPreview(map, e -> Core.app.post(() -> map.texture = new Texture("sprites/error.png")));
|
||||
createNewPreview(map, e -> Core.app.post(() -> map.texture = Core.assets.get("sprites/error.png")));
|
||||
}
|
||||
previewList.clear();
|
||||
});
|
||||
@@ -407,16 +419,4 @@ public class Maps{
|
||||
return map;
|
||||
}
|
||||
|
||||
private void loadCustomMaps(){
|
||||
for(FileHandle file : customMapDirectory.list()){
|
||||
try{
|
||||
if(file.extension().equalsIgnoreCase(mapExtension)){
|
||||
loadMap(file, true);
|
||||
}
|
||||
}catch(Exception e){
|
||||
Log.err("Failed to load custom map file '{0}'!", file);
|
||||
Log.err(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,8 +25,8 @@ public class CrashSender{
|
||||
try{
|
||||
exception.printStackTrace();
|
||||
|
||||
//don't create crash logs for me (anuke) or custom builds, as it's expected
|
||||
if(System.getProperty("user.name").equals("anuke") || Version.build == -1) return;
|
||||
//don't create crash logs for custom builds, as it's expected
|
||||
if(Version.build == -1) return;
|
||||
|
||||
//attempt to load version regardless
|
||||
if(Version.number == 0){
|
||||
|
||||
@@ -46,7 +46,9 @@ public class Net{
|
||||
t = t.getCause();
|
||||
}
|
||||
|
||||
String error = t.getMessage() == null ? "" : t.getMessage().toLowerCase();
|
||||
String baseError = Strings.getFinalMesage(e);
|
||||
|
||||
String error = baseError == null ? "" : baseError.toLowerCase();
|
||||
String type = t.getClass().toString().toLowerCase();
|
||||
boolean isError = false;
|
||||
|
||||
|
||||
@@ -67,7 +67,7 @@ public class Plugins{
|
||||
URLClassLoader classLoader = new URLClassLoader(new URL[]{jar.file().toURI().toURL()}, ClassLoader.getSystemClassLoader());
|
||||
Class<?> main = classLoader.loadClass(meta.main);
|
||||
metas.put(main, meta);
|
||||
return new LoadedPlugin(jar, zip, (Plugin)main.newInstance(), meta);
|
||||
return new LoadedPlugin(jar, zip, (Plugin)main.getDeclaredConstructor().newInstance(), meta);
|
||||
}
|
||||
|
||||
/** Represents a plugin that has been loaded from a jar file.*/
|
||||
|
||||
@@ -5,7 +5,7 @@ import io.anuke.arc.collection.ObjectMap;
|
||||
import io.anuke.arc.function.Supplier;
|
||||
import io.anuke.arc.graphics.Color;
|
||||
import io.anuke.arc.math.Mathf;
|
||||
import io.anuke.arc.util.Time;
|
||||
import io.anuke.arc.util.*;
|
||||
import io.anuke.mindustry.content.Fx;
|
||||
import io.anuke.mindustry.entities.Effects;
|
||||
import io.anuke.mindustry.entities.Effects.Effect;
|
||||
|
||||
@@ -48,7 +48,7 @@ public class CustomGameDialog extends FloatingDialog{
|
||||
maps.row();
|
||||
}
|
||||
|
||||
ImageButton image = new ImageButton(new TextureRegion(map.texture), Styles.cleari);
|
||||
ImageButton image = new ImageButton(new TextureRegion(map.safeTexture()), Styles.cleari);
|
||||
image.margin(5);
|
||||
image.top();
|
||||
|
||||
@@ -72,7 +72,7 @@ public class CustomGameDialog extends FloatingDialog{
|
||||
image.add(img).size(images);
|
||||
|
||||
|
||||
BorderImage border = new BorderImage(map.texture, 3f);
|
||||
BorderImage border = new BorderImage(map.safeTexture(), 3f);
|
||||
border.setScaling(Scaling.fit);
|
||||
image.replaceImage(border);
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ public class MapPlayDialog extends FloatingDialog{
|
||||
cont.row();
|
||||
cont.addImageTextButton("$customize", Icon.toolsSmall, () -> dialog.show(rules, () -> rules = map.applyRules(selectedGamemode))).width(230);
|
||||
cont.row();
|
||||
cont.add(new BorderImage(map.texture, 3f)).size(mobile && !Core.graphics.isPortrait() ? 150f : 250f).get().setScaling(Scaling.fit);
|
||||
cont.add(new BorderImage(map.safeTexture(), 3f)).size(mobile && !Core.graphics.isPortrait() ? 150f : 250f).get().setScaling(Scaling.fit);
|
||||
//only maps with survival are valid for high scores
|
||||
if(Gamemode.survival.valid(map)){
|
||||
cont.row();
|
||||
|
||||
@@ -4,7 +4,6 @@ import io.anuke.arc.*;
|
||||
import io.anuke.arc.graphics.*;
|
||||
import io.anuke.arc.input.*;
|
||||
import io.anuke.arc.math.*;
|
||||
import io.anuke.arc.scene.event.*;
|
||||
import io.anuke.arc.scene.ui.*;
|
||||
import io.anuke.arc.scene.ui.layout.*;
|
||||
import io.anuke.arc.util.*;
|
||||
@@ -53,12 +52,18 @@ public class MapsDialog extends FloatingDialog{
|
||||
|
||||
buttons.addImageTextButton("$editor.newmap", Icon.add, () -> {
|
||||
ui.showTextInput("$editor.newmap", "$name", "", text -> {
|
||||
ui.loadAnd(() -> {
|
||||
Runnable show = () -> ui.loadAnd(() -> {
|
||||
hide();
|
||||
ui.editor.show();
|
||||
ui.editor.editor.getTags().put("name", text);
|
||||
Events.fire(new MapMakeEvent());
|
||||
});
|
||||
|
||||
if(maps.byName(text) != null){
|
||||
ui.showErrorMessage("$editor.exists");
|
||||
}else{
|
||||
show.run();
|
||||
}
|
||||
});
|
||||
}).size(210f, 64f);
|
||||
|
||||
@@ -137,9 +142,9 @@ public class MapsDialog extends FloatingDialog{
|
||||
button.row();
|
||||
button.addImage().growX().pad(4).color(Pal.gray);
|
||||
button.row();
|
||||
button.stack(new Image(map.texture).setScaling(Scaling.fit), new BorderImage(map.texture).setScaling(Scaling.fit)).size(mapsize - 20f);
|
||||
button.stack(new Image(map.safeTexture()).setScaling(Scaling.fit), new BorderImage(map.safeTexture()).setScaling(Scaling.fit)).size(mapsize - 20f);
|
||||
button.row();
|
||||
button.add(map.custom ? "$custom" : "$builtin").color(Color.gray).padTop(3);
|
||||
button.add(map.custom ? "$custom" : map.workshop ? "$workshop" : "$builtin").color(Color.gray).padTop(3);
|
||||
|
||||
i++;
|
||||
}
|
||||
@@ -160,7 +165,7 @@ public class MapsDialog extends FloatingDialog{
|
||||
float mapsize = Core.graphics.isPortrait() ? 160f : 300f;
|
||||
Table table = dialog.cont;
|
||||
|
||||
table.stack(new Image(map.texture).setScaling(Scaling.fit), new BorderImage(map.texture).setScaling(Scaling.fit)).size(mapsize);
|
||||
table.stack(new Image(map.safeTexture()).setScaling(Scaling.fit), new BorderImage(map.safeTexture()).setScaling(Scaling.fit)).size(mapsize);
|
||||
|
||||
table.table(Styles.black, desc -> {
|
||||
desc.top();
|
||||
@@ -199,13 +204,17 @@ public class MapsDialog extends FloatingDialog{
|
||||
}
|
||||
}).fillX().height(54f).marginLeft(10);
|
||||
|
||||
table.addImageTextButton("$delete", Icon.trash16Small, () -> {
|
||||
ui.showConfirm("$confirm", Core.bundle.format("map.delete", map.name()), () -> {
|
||||
maps.removeMap(map);
|
||||
dialog.hide();
|
||||
setup();
|
||||
});
|
||||
}).fillX().height(54f).marginLeft(10).disabled(!map.custom).touchable(map.custom ? Touchable.enabled : Touchable.disabled);
|
||||
table.addImageTextButton(map.workshop ? "$view.workshop" : "$delete", map.workshop ? Icon.linkSmall : Icon.trash16Small, () -> {
|
||||
if(map.workshop){
|
||||
platform.viewMapListing(map);
|
||||
}else{
|
||||
ui.showConfirm("$confirm", Core.bundle.format("map.delete", map.name()), () -> {
|
||||
maps.removeMap(map);
|
||||
dialog.hide();
|
||||
setup();
|
||||
});
|
||||
}
|
||||
}).fillX().height(54f).marginLeft(10).disabled(!map.workshop && !map.custom);
|
||||
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ import static io.anuke.mindustry.Vars.*;
|
||||
public class BlockInventoryFragment extends Fragment{
|
||||
private final static float holdWithdraw = 20f;
|
||||
|
||||
private Table table;
|
||||
private Table table = new Table();
|
||||
private Tile tile;
|
||||
private float holdTime = 0f;
|
||||
private boolean holding;
|
||||
@@ -52,7 +52,6 @@ public class BlockInventoryFragment extends Fragment{
|
||||
|
||||
@Override
|
||||
public void build(Group parent){
|
||||
table = new Table();
|
||||
table.setName("inventory");
|
||||
table.setTransform(true);
|
||||
parent.setTransform(true);
|
||||
|
||||
@@ -572,9 +572,6 @@ public class HudFragment extends Fragment{
|
||||
}
|
||||
|
||||
shown = !shown;
|
||||
if(flip != null){
|
||||
flip.getParent().act(Core.graphics.getDeltaTime());
|
||||
}
|
||||
}
|
||||
|
||||
private void addWaveTable(Button table){
|
||||
|
||||
@@ -55,7 +55,7 @@ public class CooledTurret extends Turret{
|
||||
Liquid liquid = entity.liquids.current();
|
||||
|
||||
float used = Math.min(Math.min(entity.liquids.get(liquid), maxUsed * Time.delta()), Math.max(0, ((reload - entity.reload) / coolantMultiplier) / liquid.heatCapacity)) * baseReloadSpeed(tile);
|
||||
entity.reload += (used * liquid.heatCapacity) / liquid.heatCapacity;
|
||||
entity.reload += used * liquid.heatCapacity * coolantMultiplier;
|
||||
entity.liquids.remove(liquid, used);
|
||||
|
||||
if(Mathf.chance(0.06 * used)){
|
||||
|
||||
@@ -100,7 +100,7 @@ public abstract class Turret extends Block{
|
||||
|
||||
stats.add(BlockStat.shootRange, range / tilesize, StatUnit.blocks);
|
||||
stats.add(BlockStat.inaccuracy, (int)inaccuracy, StatUnit.degrees);
|
||||
stats.add(BlockStat.reload, 60f / reload * shots, StatUnit.none);
|
||||
stats.add(BlockStat.reload, 60f / reload, StatUnit.none);
|
||||
stats.add(BlockStat.shots, shots, StatUnit.none);
|
||||
stats.add(BlockStat.targetsAir, targetAir);
|
||||
stats.add(BlockStat.targetsGround, targetGround);
|
||||
|
||||
@@ -24,7 +24,6 @@ public class ItemBridge extends Block{
|
||||
protected int timerTransport = timers++;
|
||||
protected int range;
|
||||
protected float transportTime = 2f;
|
||||
protected IntArray removals = new IntArray();
|
||||
protected TextureRegion endRegion, bridgeRegion, arrowRegion;
|
||||
|
||||
private static int lastPlaced = Pos.invalid;
|
||||
@@ -162,21 +161,15 @@ public class ItemBridge extends Block{
|
||||
entity.time += entity.cycleSpeed * entity.delta();
|
||||
entity.time2 += (entity.cycleSpeed - 1f) * entity.delta();
|
||||
|
||||
removals.clear();
|
||||
|
||||
IntSetIterator it = entity.incoming.iterator();
|
||||
|
||||
while(it.hasNext){
|
||||
int i = it.next();
|
||||
Tile other = world.tile(i);
|
||||
if(!linkValid(tile, other, false)){
|
||||
removals.add(i);
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
for(int j = 0; j < removals.size; j++)
|
||||
entity.incoming.remove(removals.get(j));
|
||||
|
||||
Tile other = world.tile(entity.link);
|
||||
if(!linkValid(tile, other)){
|
||||
entity.link = Pos.invalid;
|
||||
@@ -184,7 +177,7 @@ public class ItemBridge extends Block{
|
||||
entity.uptime = 0f;
|
||||
}else{
|
||||
|
||||
if(entity.cons.valid()){
|
||||
if(entity.cons.valid() && (!hasPower || Mathf.isZero(1f - entity.power.satisfaction))){
|
||||
entity.uptime = Mathf.lerpDelta(entity.uptime, 1f, 0.04f);
|
||||
}else{
|
||||
entity.uptime = Mathf.lerpDelta(entity.uptime, 0f, 0.02f);
|
||||
|
||||
@@ -12,7 +12,6 @@ import io.anuke.mindustry.content.*;
|
||||
import io.anuke.mindustry.entities.*;
|
||||
import io.anuke.mindustry.entities.Effects.*;
|
||||
import io.anuke.mindustry.entities.type.*;
|
||||
import io.anuke.mindustry.entities.type.Bullet;
|
||||
import io.anuke.mindustry.gen.*;
|
||||
import io.anuke.mindustry.graphics.*;
|
||||
import io.anuke.mindustry.type.*;
|
||||
@@ -120,26 +119,28 @@ public class MassDriver extends Block{
|
||||
|
||||
if(
|
||||
tile.entity.items.total() >= minDistribute && //must shoot minimum amount of items
|
||||
link.block().itemCapacity - link.entity.items.total() >= minDistribute && //must have minimum amount of space
|
||||
entity.reload <= 0.0001f //must have reloaded
|
||||
link.block().itemCapacity - link.entity.items.total() >= minDistribute //must have minimum amount of space
|
||||
){
|
||||
MassDriverEntity other = link.entity();
|
||||
other.waitingShooters.add(tile);
|
||||
|
||||
//align to target location
|
||||
entity.rotation = Mathf.slerpDelta(entity.rotation, targetRotation, rotateSpeed * entity.power.satisfaction);
|
||||
if(entity.reload <= 0.0001f){
|
||||
|
||||
//fire when it's the first in the queue and angles are ready.
|
||||
if(other.currentShooter() == tile &&
|
||||
//align to target location
|
||||
entity.rotation = Mathf.slerpDelta(entity.rotation, targetRotation, rotateSpeed * entity.power.satisfaction);
|
||||
|
||||
//fire when it's the first in the queue and angles are ready.
|
||||
if(other.currentShooter() == tile &&
|
||||
other.state == DriverState.accepting &&
|
||||
Angles.near(entity.rotation, targetRotation, 2f) && Angles.near(other.rotation, targetRotation + 180f, 2f)){
|
||||
//actually fire
|
||||
fire(tile, link);
|
||||
//remove waiting shooters, it's done firing
|
||||
other.waitingShooters.remove(tile);
|
||||
//set both states to idle
|
||||
entity.state = DriverState.idle;
|
||||
other.state = DriverState.idle;
|
||||
//actually fire
|
||||
fire(tile, link);
|
||||
//remove waiting shooters, it's done firing
|
||||
other.waitingShooters.remove(tile);
|
||||
//set both states to idle
|
||||
entity.state = DriverState.idle;
|
||||
other.state = DriverState.idle;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package io.anuke.mindustry.world.blocks.distribution;
|
||||
|
||||
import io.anuke.arc.collection.Array;
|
||||
import io.anuke.arc.util.Time;
|
||||
import io.anuke.mindustry.content.*;
|
||||
import io.anuke.mindustry.entities.type.TileEntity;
|
||||
import io.anuke.mindustry.type.Item;
|
||||
import io.anuke.mindustry.world.*;
|
||||
@@ -63,7 +64,7 @@ public class Router extends Block{
|
||||
for(int i = 0; i < proximity.size; i++){
|
||||
Tile other = proximity.get((i + counter) % proximity.size);
|
||||
if(set) tile.rotation((byte)((tile.rotation() + 1) % proximity.size));
|
||||
if(other == from) continue;
|
||||
if(other == from && from.block() == Blocks.overflowGate) continue;
|
||||
if(other.block().acceptItem(item, other, Edges.getFacingEdge(tile, other))){
|
||||
return other;
|
||||
}
|
||||
|
||||
@@ -127,6 +127,13 @@ public class GenericCrafter extends Block{
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean outputsItems(){
|
||||
return outputItem != null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean canProduce(Tile tile){
|
||||
if(outputItem != null && tile.entity.items.get(outputItem.item) >= itemCapacity){
|
||||
|
||||
@@ -97,8 +97,10 @@ public class CoreBlock extends StorageBlock{
|
||||
entity.storageCapacity += other.block().itemCapacity + other.entity.proximity().sum(e -> isContainer(e) ? e.block().itemCapacity : 0);
|
||||
}
|
||||
|
||||
for(Item item : content.items()){
|
||||
entity.items.set(item, Math.min(entity.items.get(item), entity.storageCapacity));
|
||||
if(!world.isGenerating()){
|
||||
for(Item item : content.items()){
|
||||
entity.items.set(item, Math.min(entity.items.get(item), entity.storageCapacity));
|
||||
}
|
||||
}
|
||||
|
||||
for(Tile other : state.teams.get(tile.getTeam()).cores){
|
||||
|
||||
@@ -77,8 +77,9 @@ public class LaunchPad extends StorageBlock{
|
||||
for(Item item : Vars.content.items()){
|
||||
Events.fire(Trigger.itemLaunch);
|
||||
Effects.effect(Fx.padlaunch, tile);
|
||||
data.addItem(item, entity.items.get(item));
|
||||
entity.items.set(item, 0);
|
||||
int used = Math.min(entity.items.get(item), itemCapacity);
|
||||
data.addItem(item, used);
|
||||
entity.items.remove(item, used);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user