Merge branch 'master' of https://github.com/Anuken/Mindustry into rendering-optimizations
This commit is contained in:
@@ -17,12 +17,12 @@ import io.anuke.mindustry.game.Version;
|
||||
import io.anuke.mindustry.gen.Serialization;
|
||||
import io.anuke.mindustry.net.Net;
|
||||
import io.anuke.mindustry.world.blocks.defense.ForceProjector.ShieldEntity;
|
||||
import io.anuke.ucore.core.Settings;
|
||||
import io.anuke.ucore.entities.Entities;
|
||||
import io.anuke.ucore.entities.EntityGroup;
|
||||
import io.anuke.ucore.entities.impl.EffectEntity;
|
||||
import io.anuke.ucore.entities.trait.DrawTrait;
|
||||
import io.anuke.ucore.scene.ui.layout.Unit;
|
||||
import io.anuke.ucore.util.OS;
|
||||
import io.anuke.ucore.util.Translator;
|
||||
|
||||
import java.util.Arrays;
|
||||
@@ -169,7 +169,7 @@ public class Vars{
|
||||
ios = Gdx.app.getType() == ApplicationType.iOS;
|
||||
android = Gdx.app.getType() == ApplicationType.Android;
|
||||
|
||||
dataDirectory = OS.getAppDataDirectory(appName);
|
||||
dataDirectory = Settings.getDataDirectory(appName);
|
||||
customMapDirectory = dataDirectory.child("maps/");
|
||||
saveDirectory = dataDirectory.child("saves/");
|
||||
baseCameraScale = Math.round(Unit.dp.scl(4));
|
||||
|
||||
@@ -45,6 +45,8 @@ public class Blocks extends BlockList implements ContentList{
|
||||
}
|
||||
};
|
||||
|
||||
//Registers build blocks from size 1-6
|
||||
//no reference is needed here since they can be looked up by name later
|
||||
for(int i = 1; i <= 6; i++){
|
||||
new BuildBlock("build" + i);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,9 @@ import io.anuke.mindustry.game.Teams;
|
||||
import io.anuke.mindustry.net.Net;
|
||||
import io.anuke.ucore.core.Events;
|
||||
|
||||
import static io.anuke.mindustry.Vars.unitGroups;
|
||||
import static io.anuke.mindustry.Vars.waveTeam;
|
||||
|
||||
public class GameState{
|
||||
public int wave = 1;
|
||||
public float wavetime;
|
||||
@@ -16,8 +19,13 @@ public class GameState{
|
||||
public Difficulty difficulty = Difficulty.normal;
|
||||
public WaveSpawner spawner = new WaveSpawner();
|
||||
public Teams teams = new Teams();
|
||||
public int enemies;
|
||||
private State state = State.menu;
|
||||
|
||||
public int enemies(){
|
||||
return Net.client() ? enemies : unitGroups[waveTeam.ordinal()].size();
|
||||
}
|
||||
|
||||
public void set(State astate){
|
||||
Events.fire(new StateChangeEvent(state, astate));
|
||||
state = astate;
|
||||
|
||||
@@ -125,7 +125,7 @@ public class Logic extends Module{
|
||||
}
|
||||
|
||||
private void updateSectors(){
|
||||
if(world.getSector() == null) return;
|
||||
if(world.getSector() == null || state.gameOver) return;
|
||||
|
||||
world.getSector().currentMission().update();
|
||||
|
||||
@@ -218,12 +218,6 @@ public class Logic extends Module{
|
||||
if(group.isEmpty()) continue;
|
||||
|
||||
EntityQuery.collideGroups(bulletGroup, group);
|
||||
EntityQuery.collideGroups(group, playerGroup);
|
||||
|
||||
for(EntityGroup other : unitGroups){
|
||||
if(other.isEmpty()) continue;
|
||||
EntityQuery.collideGroups(group, other);
|
||||
}
|
||||
}
|
||||
|
||||
EntityQuery.collideGroups(bulletGroup, playerGroup);
|
||||
|
||||
@@ -45,7 +45,7 @@ import static io.anuke.mindustry.Vars.*;
|
||||
public class NetClient extends Module{
|
||||
private final static float dataTimeout = 60 * 18;
|
||||
private final static float playerSyncTime = 2;
|
||||
private final static float viewScale = 1.75f;
|
||||
public final static float viewScale = 2f;
|
||||
|
||||
private Timer timer = new Timer(5);
|
||||
/**Whether the client is currently connecting.*/
|
||||
@@ -284,6 +284,7 @@ public class NetClient extends Module{
|
||||
//read wave info
|
||||
state.wavetime = input.readFloat();
|
||||
state.wave = input.readInt();
|
||||
state.enemies = input.readInt();
|
||||
|
||||
byte cores = input.readByte();
|
||||
for(int i = 0; i < cores; i++){
|
||||
|
||||
@@ -412,7 +412,16 @@ public class NetServer extends Module{
|
||||
}
|
||||
|
||||
public boolean isWaitingForPlayers(){
|
||||
return state.mode.isPvp && playerGroup.size() < 2;
|
||||
if(state.mode.isPvp){
|
||||
int used = 0;
|
||||
for(Team t : Team.all){
|
||||
if(playerGroup.count(p -> p.getTeam() == t) > 0){
|
||||
used ++;
|
||||
}
|
||||
}
|
||||
return used < 2;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void update(){
|
||||
@@ -468,6 +477,7 @@ public class NetServer extends Module{
|
||||
//write wave datas
|
||||
dataStream.writeFloat(state.wavetime);
|
||||
dataStream.writeInt(state.wave);
|
||||
dataStream.writeInt(state.enemies());
|
||||
|
||||
ObjectSet<Tile> cores = state.teams.get(player.getTeam()).cores;
|
||||
|
||||
@@ -494,7 +504,7 @@ public class NetServer extends Module{
|
||||
//check for syncable groups
|
||||
for(EntityGroup<?> group : Entities.getAllGroups()){
|
||||
if(group.isEmpty() || !(group.all().get(0) instanceof SyncTrait)) continue;
|
||||
//clipping is done by represntatives
|
||||
//clipping is done by representatives
|
||||
SyncTrait represent = (SyncTrait) group.all().get(0);
|
||||
|
||||
//make sure mapping is enabled for this group
|
||||
|
||||
@@ -1,13 +1,21 @@
|
||||
package io.anuke.mindustry.core;
|
||||
|
||||
import com.badlogic.gdx.Gdx;
|
||||
import com.badlogic.gdx.Input.Keys;
|
||||
import com.badlogic.gdx.files.FileHandle;
|
||||
import com.badlogic.gdx.utils.Base64Coder;
|
||||
import io.anuke.ucore.core.Core;
|
||||
import io.anuke.ucore.core.Settings;
|
||||
import io.anuke.ucore.core.Timers;
|
||||
import io.anuke.ucore.function.Consumer;
|
||||
import io.anuke.ucore.scene.ui.Dialog;
|
||||
import io.anuke.ucore.scene.ui.TextField;
|
||||
import io.anuke.ucore.util.Log;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
import static io.anuke.mindustry.Vars.mobile;
|
||||
|
||||
public abstract class Platform {
|
||||
/**Each separate game platform should set this instance to their own implementation.*/
|
||||
public static Platform instance = new Platform() {};
|
||||
@@ -17,7 +25,34 @@ public abstract class Platform {
|
||||
addDialog(field, 16);
|
||||
}
|
||||
/**See addDialog().*/
|
||||
public void addDialog(TextField field, int maxLength){}
|
||||
public void addDialog(TextField field, int maxLength){
|
||||
if(!mobile) return; //this is mobile only, desktop doesn't need dialogs
|
||||
|
||||
field.tapped(() -> {
|
||||
Log.info("yappd");
|
||||
Dialog dialog = new Dialog("", "dialog");
|
||||
dialog.setFillParent(true);
|
||||
dialog.content().top();
|
||||
dialog.content().defaults().height(65f);
|
||||
TextField to = dialog.content().addField(field.getText(), t-> {}).pad(15).width(250f).get();
|
||||
to.setMaxLength(maxLength);
|
||||
to.keyDown(Keys.ENTER, () -> dialog.content().find("okb").fireClick());
|
||||
dialog.content().addButton("$text.ok", () -> {
|
||||
field.clearText();
|
||||
field.appendText(to.getText());
|
||||
field.change();
|
||||
dialog.hide();
|
||||
Gdx.input.setOnscreenKeyboardVisible(false);
|
||||
}).width(90f).name("okb");
|
||||
|
||||
dialog.show();
|
||||
Timers.runTask(1f, () -> {
|
||||
to.setCursorPosition(to.getText().length());
|
||||
Core.scene.setKeyboardFocus(to);
|
||||
Gdx.input.setOnscreenKeyboardVisible(true);
|
||||
});
|
||||
});
|
||||
}
|
||||
/**Update discord RPC.*/
|
||||
public void updateRPC(){}
|
||||
/**Called when the game is exited.*/
|
||||
|
||||
@@ -11,7 +11,7 @@ public class ThreadHandler{
|
||||
public ThreadHandler(){
|
||||
Timers.setDeltaProvider(() -> {
|
||||
float result = Gdx.graphics.getDeltaTime() * 60f;
|
||||
return Math.min(Float.isNaN(result) || Float.isInfinite(result) ? 1f : result, 15f);
|
||||
return Float.isNaN(result) || Float.isInfinite(result) ? 1f : Math.min(result, 60f / 10f);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -293,7 +293,7 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
||||
float x = snappedX(), y = snappedY();
|
||||
|
||||
if(!movement.isZero() && moved && !state.isPaused()){
|
||||
walktime += Timers.delta() * movement.len() / 0.7f * getFloorOn().speedMultiplier;
|
||||
walktime += movement.len() / 0.7f * getFloorOn().speedMultiplier;
|
||||
baseRotation = Mathf.slerpDelta(baseRotation, movement.angle(), 0.13f);
|
||||
}
|
||||
|
||||
@@ -554,8 +554,8 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
||||
|
||||
updateBuilding(this);
|
||||
|
||||
x = Mathf.clamp(x, 0, world.width() * tilesize);
|
||||
y = Mathf.clamp(y, 0, world.height() * tilesize);
|
||||
x = Mathf.clamp(x, tilesize, world.width() * tilesize - tilesize);
|
||||
y = Mathf.clamp(y, tilesize, world.height() * tilesize - tilesize);
|
||||
}
|
||||
|
||||
protected void updateMech(){
|
||||
@@ -612,11 +612,11 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
||||
pointerY = vec.y;
|
||||
updateShooting();
|
||||
|
||||
movement.limit(speed * Timers.delta());
|
||||
movement.limit(speed).scl(Timers.delta());
|
||||
|
||||
if(getCarrier() == null){
|
||||
if(!ui.chatfrag.chatOpen()){
|
||||
velocity.add(movement);
|
||||
velocity.add(movement.x, movement.y);
|
||||
}
|
||||
float prex = x, prey = y;
|
||||
updateVelocityStatus();
|
||||
@@ -813,6 +813,12 @@ public class Player extends Unit implements BuilderTrait, CarryTrait, ShooterTra
|
||||
|
||||
//region read and write methods
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isClipped(){
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeSave(DataOutput stream) throws IOException{
|
||||
stream.writeBoolean(isLocal);
|
||||
|
||||
@@ -233,7 +233,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
||||
|
||||
status.update(this);
|
||||
|
||||
velocity.limit(getMaxVelocity()).scl(status.getSpeedMultiplier());
|
||||
velocity.limit(getMaxVelocity()).scl(1f + (status.getSpeedMultiplier()-1f) * Timers.delta());
|
||||
|
||||
if(isFlying()){
|
||||
x += velocity.x * Timers.delta();
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
package io.anuke.mindustry.entities.traits;
|
||||
|
||||
import io.anuke.mindustry.core.NetClient;
|
||||
import io.anuke.mindustry.net.Interpolator;
|
||||
import io.anuke.ucore.core.Core;
|
||||
import io.anuke.ucore.entities.trait.Entity;
|
||||
import io.anuke.ucore.util.Tmp;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
@@ -24,8 +27,21 @@ public interface SyncTrait extends Entity, TypeTrait{
|
||||
|
||||
/**Interpolate entity position only. Override if you need to interpolate rotations or other values.*/
|
||||
default void interpolate(){
|
||||
if(getInterpolator() == null)
|
||||
if(getInterpolator() == null){
|
||||
throw new RuntimeException("This entity must have an interpolator to interpolate()!");
|
||||
}
|
||||
|
||||
if(isClipped()){
|
||||
//move off screen when no longer in bounds
|
||||
Tmp.r1.setSize(Core.camera.viewportWidth * Core.camera.zoom * NetClient.viewScale,
|
||||
Core.camera.viewportHeight * Core.camera.zoom * NetClient.viewScale)
|
||||
.setCenter(Core.camera.position.x, Core.camera.position.y);
|
||||
|
||||
if(!Tmp.r1.contains(getX(), getY()) && !Tmp.r1.contains(getInterpolator().last.x, getInterpolator().last.y)){
|
||||
set(-99999f, -99999f);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
getInterpolator().update();
|
||||
|
||||
|
||||
@@ -238,7 +238,7 @@ public abstract class GroundUnit extends BaseUnit{
|
||||
}
|
||||
|
||||
protected void patrol(){
|
||||
vec.trns(baseRotation, type.speed);
|
||||
vec.trns(baseRotation, type.speed * Timers.delta());
|
||||
velocity.add(vec.x, vec.y);
|
||||
vec.trns(baseRotation, type.hitsizeTile);
|
||||
Tile tile = world.tileWorld(x + vec.x, y + vec.y);
|
||||
|
||||
@@ -80,7 +80,7 @@ public class MinimapRenderer implements Disposable{
|
||||
for(Unit unit : units){
|
||||
float rx = (unit.x - rect.x) / rect.width * w, ry = (unit.y - rect.y) / rect.width * h;
|
||||
Draw.color(unit.getTeam().color);
|
||||
Draw.rect("white", x + rx, y + ry, w / (sz * 2), h / (sz * 2));
|
||||
Draw.crect(Draw.getBlankRegion(), x + rx, y + ry, w / (sz * 2), h / (sz * 2));
|
||||
}
|
||||
|
||||
Draw.color();
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
package io.anuke.mindustry.maps.generation.pathfinding;
|
||||
|
||||
import com.badlogic.gdx.math.GridPoint2;
|
||||
import com.badlogic.gdx.math.MathUtils;
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import com.badlogic.gdx.utils.Queue;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.ucore.function.Predicate;
|
||||
import io.anuke.ucore.util.Geometry;
|
||||
|
||||
public class FlowPathFinder extends TilePathfinder{
|
||||
protected float[][] weights;
|
||||
|
||||
public FlowPathFinder(Tile[][] tiles){
|
||||
super(tiles);
|
||||
this.weights = new float[tiles.length][tiles[0].length];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void search(Tile start, Tile end, Array<Tile> out){
|
||||
|
||||
}
|
||||
|
||||
public void search(Tile start, Predicate<Tile> result, Array<Tile> out){
|
||||
Queue<Tile> queue = new Queue<>();
|
||||
|
||||
for(int i = 0; i < weights.length; i++){
|
||||
for(int j = 0; j < weights[0].length; j++){
|
||||
if(result.test(tiles[i][j])){
|
||||
weights[i][j] = 100000;
|
||||
queue.addLast(tiles[i][j]);
|
||||
}else{
|
||||
weights[i][j] = 0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while(queue.size > 0){
|
||||
Tile tile = queue.first();
|
||||
for(GridPoint2 point : Geometry.d4){
|
||||
int nx = tile.x + point.x, ny = tile.y + point.y;
|
||||
if(inBounds(nx, ny) && weights[nx][ny] < weights[tile.x][tile.y] - 1f && tiles[nx][ny].passable()){
|
||||
weights[nx][ny] = weights[tile.x][tile.y] - 1;
|
||||
queue.addLast(tiles[nx][ny]);
|
||||
if(result.test(tiles[nx][ny])){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out.add(start);
|
||||
while(true){
|
||||
Tile tile = out.peek();
|
||||
|
||||
Tile max = null;
|
||||
float maxf = weights[tile.x][tile.y];
|
||||
for(GridPoint2 point : Geometry.d4){
|
||||
int nx = tile.x + point.x, ny = tile.y + point.y;
|
||||
if(inBounds(nx, ny) && (weights[nx][ny] > maxf)){
|
||||
max = tiles[nx][ny];
|
||||
maxf = weights[nx][ny];
|
||||
|
||||
if(MathUtils.isEqual(maxf, 100000)){
|
||||
out.add(max);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(max == null){
|
||||
break;
|
||||
}
|
||||
out.add(max);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package io.anuke.mindustry.maps.generation.pathfinding;
|
||||
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.ucore.util.Structs;
|
||||
|
||||
public abstract class TilePathfinder{
|
||||
protected Tile[][] tiles;
|
||||
|
||||
public TilePathfinder(Tile[][] tiles){
|
||||
this.tiles = tiles;
|
||||
}
|
||||
|
||||
protected boolean inBounds(int x, int y){
|
||||
return Structs.inBounds(x, y, tiles);
|
||||
}
|
||||
|
||||
public abstract void search(Tile start, Tile end, Array<Tile> out);
|
||||
}
|
||||
@@ -1,14 +1,12 @@
|
||||
package io.anuke.mindustry.maps.missions;
|
||||
|
||||
import com.badlogic.gdx.utils.Array;
|
||||
import io.anuke.mindustry.Vars;
|
||||
import io.anuke.mindustry.game.GameMode;
|
||||
import io.anuke.mindustry.game.SpawnGroup;
|
||||
import io.anuke.mindustry.game.Team;
|
||||
import io.anuke.mindustry.game.Waves;
|
||||
import io.anuke.mindustry.maps.Sector;
|
||||
import io.anuke.mindustry.maps.generation.Generation;
|
||||
import io.anuke.mindustry.net.Net;
|
||||
import io.anuke.ucore.util.Bundles;
|
||||
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
@@ -62,9 +60,9 @@ public class WaveMission extends MissionWithStartingCore{
|
||||
public String displayString(){
|
||||
return state.wave > target ?
|
||||
Bundles.format(
|
||||
Vars.unitGroups[Vars.waveTeam.ordinal()].size() > 1 && !Net.client() ?
|
||||
state.enemies() > 1 ?
|
||||
"text.mission.wave.enemies" :
|
||||
"text.mission.wave.enemy", target, target, Vars.unitGroups[Vars.waveTeam.ordinal()].size()) :
|
||||
"text.mission.wave.enemy", target, target, state.enemies()) :
|
||||
Bundles.format("text.mission.wave", state.wave, target, (int)(state.wavetime/60));
|
||||
}
|
||||
|
||||
@@ -82,6 +80,6 @@ public class WaveMission extends MissionWithStartingCore{
|
||||
|
||||
@Override
|
||||
public boolean isComplete(){
|
||||
return state.wave > target && Vars.unitGroups[Vars.waveTeam.ordinal()].size() == 0;
|
||||
return state.wave > target && state.enemies() == 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -366,10 +366,10 @@ public class HudFragment extends Fragment{
|
||||
|
||||
table.labelWrap(() ->
|
||||
world.getSector() == null ?
|
||||
(unitGroups[waveTeam.ordinal()].size() > 0 && state.mode.disableWaveTimer ?
|
||||
wavef.get(state.wave) + "\n" + (unitGroups[waveTeam.ordinal()].size() == 1 ?
|
||||
enemyf.get(unitGroups[waveTeam.ordinal()].size()) :
|
||||
enemiesf.get(unitGroups[waveTeam.ordinal()].size())) :
|
||||
(state.enemies() > 0 && state.mode.disableWaveTimer ?
|
||||
wavef.get(state.wave) + "\n" + (state.enemies() == 1 ?
|
||||
enemyf.get(state.enemies()) :
|
||||
enemiesf.get(state.enemies())) :
|
||||
wavef.get(state.wave) + "\n" +
|
||||
(!state.mode.disableWaveTimer ?
|
||||
Bundles.format("text.wave.waiting", (int)(state.wavetime/60)) :
|
||||
|
||||
@@ -11,12 +11,12 @@ import io.anuke.mindustry.world.Tile;
|
||||
import io.anuke.mindustry.world.blocks.SelectionTrait;
|
||||
import io.anuke.ucore.graphics.Draw;
|
||||
import io.anuke.ucore.scene.ui.layout.Table;
|
||||
import io.anuke.ucore.util.Log;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import static io.anuke.mindustry.Vars.*;
|
||||
|
||||
import static io.anuke.mindustry.Vars.content;
|
||||
|
||||
public class SortedUnloader extends Unloader implements SelectionTrait{
|
||||
protected float speed = 1f;
|
||||
@@ -38,7 +38,6 @@ public class SortedUnloader extends Unloader implements SelectionTrait{
|
||||
SortedUnloaderEntity entity = tile.entity();
|
||||
|
||||
if(tile.entity.timer.get(timerUnload, speed) && tile.entity.items.total() == 0){
|
||||
Log.info(threads.getFrameID());
|
||||
for(Tile other : tile.entity.proximity()){
|
||||
if(other.getTeam() == tile.getTeam() && other.block() instanceof StorageBlock && entity.items.total() == 0 &&
|
||||
((entity.sortItem == null && other.entity.items.total() > 0) || ((StorageBlock) other.block()).hasItem(other, entity.sortItem))){
|
||||
|
||||
@@ -71,7 +71,7 @@ public class UnitFactory extends Block{
|
||||
if(!Net.client()){
|
||||
BaseUnit unit = factory.type.create(tile.getTeam());
|
||||
unit.setSpawner(tile);
|
||||
unit.set(tile.drawx(), tile.drawy());
|
||||
unit.set(tile.drawx() + Mathf.range(4), tile.drawy() + Mathf.range(4));
|
||||
unit.add();
|
||||
unit.getVelocity().y = factory.launchVelocity;
|
||||
}
|
||||
|
||||
@@ -28,6 +28,10 @@ public class PowerModule extends BlockModule{
|
||||
if(Float.isNaN(amount)){
|
||||
amount = 0f;
|
||||
}
|
||||
// Workaround: If power went negative for some reason, at least fix it when reloading the map
|
||||
if(amount < 0f){
|
||||
amount = 0f;
|
||||
}
|
||||
|
||||
short amount = stream.readShort();
|
||||
for(int i = 0; i < amount; i++){
|
||||
|
||||
Reference in New Issue
Block a user