Merge branch 'master' into crater
This commit is contained in:
@@ -16,4 +16,5 @@ const boolp = method => new Boolp(){get: method}
|
|||||||
const cons = method => new Cons(){get: method}
|
const cons = method => new Cons(){get: method}
|
||||||
const prov = method => new Prov(){get: method}
|
const prov = method => new Prov(){get: method}
|
||||||
const newEffect = (lifetime, renderer) => new Effects.Effect(lifetime, new Effects.EffectRenderer({render: renderer}))
|
const newEffect = (lifetime, renderer) => new Effects.Effect(lifetime, new Effects.EffectRenderer({render: renderer}))
|
||||||
const Calls = Packages.io.anuke.mindustry.gen.Call
|
Call = Packages.io.anuke.mindustry.gen.Call
|
||||||
|
const Calls = Call //backwards compat
|
||||||
@@ -18,7 +18,8 @@ const boolp = method => new Boolp(){get: method}
|
|||||||
const cons = method => new Cons(){get: method}
|
const cons = method => new Cons(){get: method}
|
||||||
const prov = method => new Prov(){get: method}
|
const prov = method => new Prov(){get: method}
|
||||||
const newEffect = (lifetime, renderer) => new Effects.Effect(lifetime, new Effects.EffectRenderer({render: renderer}))
|
const newEffect = (lifetime, renderer) => new Effects.Effect(lifetime, new Effects.EffectRenderer({render: renderer}))
|
||||||
const Calls = Packages.io.anuke.mindustry.gen.Call
|
Call = Packages.io.anuke.mindustry.gen.Call
|
||||||
|
const Calls = Call //backwards compat
|
||||||
importPackage(Packages.arc)
|
importPackage(Packages.arc)
|
||||||
importPackage(Packages.arc.func)
|
importPackage(Packages.arc.func)
|
||||||
importPackage(Packages.arc.graphics)
|
importPackage(Packages.arc.graphics)
|
||||||
|
|||||||
@@ -61,10 +61,6 @@ public class Vars implements Loadable{
|
|||||||
public static final Array<String> defaultServers = Array.with();
|
public static final Array<String> defaultServers = Array.with();
|
||||||
/** maximum distance between mine and core that supports automatic transferring */
|
/** maximum distance between mine and core that supports automatic transferring */
|
||||||
public static final float mineTransferRange = 220f;
|
public static final float mineTransferRange = 220f;
|
||||||
/** team of the player by default */
|
|
||||||
public static final Team defaultTeam = Team.sharded;
|
|
||||||
/** team of the enemy in waves/sectors */
|
|
||||||
public static final Team waveTeam = Team.crux;
|
|
||||||
/** whether to enable editing of units in the editor */
|
/** whether to enable editing of units in the editor */
|
||||||
public static final boolean enableUnitEditing = false;
|
public static final boolean enableUnitEditing = false;
|
||||||
/** max chat message length */
|
/** max chat message length */
|
||||||
@@ -128,9 +124,9 @@ public class Vars implements Loadable{
|
|||||||
public static Fi dataDirectory;
|
public static Fi dataDirectory;
|
||||||
/** data subdirectory used for screenshots */
|
/** data subdirectory used for screenshots */
|
||||||
public static Fi screenshotDirectory;
|
public static Fi screenshotDirectory;
|
||||||
/** data subdirectory used for custom mmaps */
|
/** data subdirectory used for custom maps */
|
||||||
public static Fi customMapDirectory;
|
public static Fi customMapDirectory;
|
||||||
/** data subdirectory used for custom mmaps */
|
/** data subdirectory used for custom map previews */
|
||||||
public static Fi mapPreviewDirectory;
|
public static Fi mapPreviewDirectory;
|
||||||
/** tmp subdirectory for map conversion */
|
/** tmp subdirectory for map conversion */
|
||||||
public static Fi tmpDirectory;
|
public static Fi tmpDirectory;
|
||||||
@@ -184,7 +180,7 @@ public class Vars implements Loadable{
|
|||||||
public static EntityGroup<ShieldEntity> shieldGroup;
|
public static EntityGroup<ShieldEntity> shieldGroup;
|
||||||
public static EntityGroup<Puddle> puddleGroup;
|
public static EntityGroup<Puddle> puddleGroup;
|
||||||
public static EntityGroup<Fire> fireGroup;
|
public static EntityGroup<Fire> fireGroup;
|
||||||
public static EntityGroup<BaseUnit>[] unitGroups;
|
public static EntityGroup<BaseUnit> unitGroup;
|
||||||
|
|
||||||
public static Player player;
|
public static Player player;
|
||||||
|
|
||||||
@@ -239,11 +235,7 @@ public class Vars implements Loadable{
|
|||||||
puddleGroup = entities.add(Puddle.class).enableMapping();
|
puddleGroup = entities.add(Puddle.class).enableMapping();
|
||||||
shieldGroup = entities.add(ShieldEntity.class, false);
|
shieldGroup = entities.add(ShieldEntity.class, false);
|
||||||
fireGroup = entities.add(Fire.class).enableMapping();
|
fireGroup = entities.add(Fire.class).enableMapping();
|
||||||
unitGroups = new EntityGroup[Team.all.length];
|
unitGroup = entities.add(BaseUnit.class).enableMapping();
|
||||||
|
|
||||||
for(Team team : Team.all){
|
|
||||||
unitGroups[team.ordinal()] = entities.add(BaseUnit.class).enableMapping();
|
|
||||||
}
|
|
||||||
|
|
||||||
for(EntityGroup<?> group : entities.all()){
|
for(EntityGroup<?> group : entities.all()){
|
||||||
group.setRemoveListener(entity -> {
|
group.setRemoveListener(entity -> {
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package mindustry.ai;
|
package mindustry.ai;
|
||||||
|
|
||||||
import arc.*;
|
import arc.*;
|
||||||
import arc.struct.*;
|
|
||||||
import arc.func.*;
|
import arc.func.*;
|
||||||
import arc.math.*;
|
import arc.math.*;
|
||||||
import arc.math.geom.*;
|
import arc.math.geom.*;
|
||||||
|
import arc.struct.*;
|
||||||
import mindustry.content.*;
|
import mindustry.content.*;
|
||||||
import mindustry.entities.type.*;
|
import mindustry.entities.type.*;
|
||||||
import mindustry.game.EventType.*;
|
import mindustry.game.EventType.*;
|
||||||
@@ -28,15 +28,15 @@ public class BlockIndexer{
|
|||||||
private final ObjectSet<Item> itemSet = new ObjectSet<>();
|
private final ObjectSet<Item> itemSet = new ObjectSet<>();
|
||||||
/** Stores all ore quadtrants on the map. */
|
/** Stores all ore quadtrants on the map. */
|
||||||
private ObjectMap<Item, ObjectSet<Tile>> ores = new ObjectMap<>();
|
private ObjectMap<Item, ObjectSet<Tile>> ores = new ObjectMap<>();
|
||||||
/** Tags all quadrants. */
|
/** Maps each team ID to a quarant. A quadrant is a grid of bits, where each bit is set if and only if there is a block of that team in that quadrant. */
|
||||||
private GridBits[] structQuadrants;
|
private GridBits[] structQuadrants;
|
||||||
/** Stores all damaged tile entities by team. */
|
/** Stores all damaged tile entities by team. */
|
||||||
private ObjectSet<Tile>[] damagedTiles = new ObjectSet[Team.all.length];
|
private ObjectSet<Tile>[] damagedTiles = new ObjectSet[Team.all().length];
|
||||||
/**All ores available on this map.*/
|
/**All ores available on this map.*/
|
||||||
private ObjectSet<Item> allOres = new ObjectSet<>();
|
private ObjectSet<Item> allOres = new ObjectSet<>();
|
||||||
|
|
||||||
/** Maps teams to a map of flagged tiles by type. */
|
/** Maps teams to a map of flagged tiles by type. */
|
||||||
private ObjectSet<Tile>[][] flagMap = new ObjectSet[Team.all.length][BlockFlag.all.length];
|
private ObjectSet<Tile>[][] flagMap = new ObjectSet[Team.all().length][BlockFlag.all.length];
|
||||||
/** Maps tile positions to their last known tile index data. */
|
/** Maps tile positions to their last known tile index data. */
|
||||||
private IntMap<TileIndex> typeMap = new IntMap<>();
|
private IntMap<TileIndex> typeMap = new IntMap<>();
|
||||||
/** Empty set used for returning. */
|
/** Empty set used for returning. */
|
||||||
@@ -59,8 +59,8 @@ public class BlockIndexer{
|
|||||||
Events.on(WorldLoadEvent.class, event -> {
|
Events.on(WorldLoadEvent.class, event -> {
|
||||||
scanOres.clear();
|
scanOres.clear();
|
||||||
scanOres.addAll(Item.getAllOres());
|
scanOres.addAll(Item.getAllOres());
|
||||||
damagedTiles = new ObjectSet[Team.all.length];
|
damagedTiles = new ObjectSet[Team.all().length];
|
||||||
flagMap = new ObjectSet[Team.all.length][BlockFlag.all.length];
|
flagMap = new ObjectSet[Team.all().length][BlockFlag.all.length];
|
||||||
|
|
||||||
for(int i = 0; i < flagMap.length; i++){
|
for(int i = 0; i < flagMap.length; i++){
|
||||||
for(int j = 0; j < BlockFlag.all.length; j++){
|
for(int j = 0; j < BlockFlag.all.length; j++){
|
||||||
@@ -73,10 +73,7 @@ public class BlockIndexer{
|
|||||||
ores = null;
|
ores = null;
|
||||||
|
|
||||||
//create bitset for each team type that contains each quadrant
|
//create bitset for each team type that contains each quadrant
|
||||||
structQuadrants = new GridBits[Team.all.length];
|
structQuadrants = new GridBits[Team.all().length];
|
||||||
for(int i = 0; i < Team.all.length; i++){
|
|
||||||
structQuadrants[i] = new GridBits(Mathf.ceil(world.width() / (float)quadrantSize), Mathf.ceil(world.height() / (float)quadrantSize));
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int x = 0; x < world.width(); x++){
|
for(int x = 0; x < world.width(); x++){
|
||||||
for(int y = 0; y < world.height(); y++){
|
for(int y = 0; y < world.height(); y++){
|
||||||
@@ -103,7 +100,31 @@ public class BlockIndexer{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ObjectSet<Tile>[] getFlagged(Team team){
|
private ObjectSet<Tile>[] getFlagged(Team team){
|
||||||
return flagMap[team.ordinal()];
|
return flagMap[team.id];
|
||||||
|
}
|
||||||
|
|
||||||
|
private GridBits structQuadrant(Team t){
|
||||||
|
if(structQuadrants[t.id] == null){
|
||||||
|
structQuadrants[t.id] = new GridBits(Mathf.ceil(world.width() / (float)quadrantSize), Mathf.ceil(world.height() / (float)quadrantSize));
|
||||||
|
}
|
||||||
|
return structQuadrants[t.id];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Updates all the structure quadrants for a newly activated team. */
|
||||||
|
public void updateTeamIndex(Team team){
|
||||||
|
if(structQuadrants == null) return;
|
||||||
|
|
||||||
|
//go through every tile... ouch
|
||||||
|
for(int x = 0; x < world.width(); x++){
|
||||||
|
for(int y = 0; y < world.height(); y++){
|
||||||
|
Tile tile = world.tile(x, y);
|
||||||
|
if(tile.getTeam() == team){
|
||||||
|
int quadrantX = tile.x / quadrantSize;
|
||||||
|
int quadrantY = tile.y / quadrantSize;
|
||||||
|
structQuadrant(team).set(quadrantX, quadrantY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @return whether this item is present on this map.*/
|
/** @return whether this item is present on this map.*/
|
||||||
@@ -115,11 +136,11 @@ public class BlockIndexer{
|
|||||||
public ObjectSet<Tile> getDamaged(Team team){
|
public ObjectSet<Tile> getDamaged(Team team){
|
||||||
returnArray.clear();
|
returnArray.clear();
|
||||||
|
|
||||||
if(damagedTiles[team.ordinal()] == null){
|
if(damagedTiles[team.id] == null){
|
||||||
damagedTiles[team.ordinal()] = new ObjectSet<>();
|
damagedTiles[team.id] = new ObjectSet<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectSet<Tile> set = damagedTiles[team.ordinal()];
|
ObjectSet<Tile> set = damagedTiles[team.id];
|
||||||
for(Tile tile : set){
|
for(Tile tile : set){
|
||||||
if((tile.entity == null || tile.entity.getTeam() != team || !tile.entity.damaged()) || tile.block() instanceof BuildBlock){
|
if((tile.entity == null || tile.entity.getTeam() != team || !tile.entity.damaged()) || tile.block() instanceof BuildBlock){
|
||||||
returnArray.add(tile);
|
returnArray.add(tile);
|
||||||
@@ -135,13 +156,13 @@ public class BlockIndexer{
|
|||||||
|
|
||||||
/** Get all allied blocks with a flag. */
|
/** Get all allied blocks with a flag. */
|
||||||
public ObjectSet<Tile> getAllied(Team team, BlockFlag type){
|
public ObjectSet<Tile> getAllied(Team team, BlockFlag type){
|
||||||
return flagMap[team.ordinal()][type.ordinal()];
|
return flagMap[team.id][type.ordinal()];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Get all enemy blocks with a flag. */
|
/** Get all enemy blocks with a flag. */
|
||||||
public Array<Tile> getEnemy(Team team, BlockFlag type){
|
public Array<Tile> getEnemy(Team team, BlockFlag type){
|
||||||
returnArray.clear();
|
returnArray.clear();
|
||||||
for(Team enemy : state.teams.enemiesOf(team)){
|
for(Team enemy : team.enemies()){
|
||||||
if(state.teams.isActive(enemy)){
|
if(state.teams.isActive(enemy)){
|
||||||
ObjectSet<Tile> set = getFlagged(enemy)[type.ordinal()];
|
ObjectSet<Tile> set = getFlagged(enemy)[type.ordinal()];
|
||||||
if(set != null){
|
if(set != null){
|
||||||
@@ -155,11 +176,11 @@ public class BlockIndexer{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void notifyTileDamaged(TileEntity entity){
|
public void notifyTileDamaged(TileEntity entity){
|
||||||
if(damagedTiles[entity.getTeam().ordinal()] == null){
|
if(damagedTiles[(int)entity.getTeam().id] == null){
|
||||||
damagedTiles[entity.getTeam().ordinal()] = new ObjectSet<>();
|
damagedTiles[(int)entity.getTeam().id] = new ObjectSet<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectSet<Tile> set = damagedTiles[entity.getTeam().ordinal()];
|
ObjectSet<Tile> set = damagedTiles[(int)entity.getTeam().id];
|
||||||
set.add(entity.tile);
|
set.add(entity.tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -282,16 +303,16 @@ public class BlockIndexer{
|
|||||||
int quadrantY = tile.y / quadrantSize;
|
int quadrantY = tile.y / quadrantSize;
|
||||||
int index = quadrantX + quadrantY * quadWidth();
|
int index = quadrantX + quadrantY * quadWidth();
|
||||||
|
|
||||||
for(Team team : Team.all){
|
for(TeamData data : state.teams.getActive()){
|
||||||
TeamData data = state.teams.get(team);
|
GridBits bits = structQuadrant(data.team);
|
||||||
|
|
||||||
//fast-set this quadrant to 'occupied' if the tile just placed is already of this team
|
//fast-set this quadrant to 'occupied' if the tile just placed is already of this team
|
||||||
if(tile.getTeam() == data.team && tile.entity != null && tile.block().targetable){
|
if(tile.getTeam() == data.team && tile.entity != null && tile.block().targetable){
|
||||||
structQuadrants[data.team.ordinal()].set(quadrantX, quadrantY);
|
bits.set(quadrantX, quadrantY);
|
||||||
continue; //no need to process futher
|
continue; //no need to process futher
|
||||||
}
|
}
|
||||||
|
|
||||||
structQuadrants[data.team.ordinal()].set(quadrantX, quadrantY, false);
|
bits.set(quadrantX, quadrantY, false);
|
||||||
|
|
||||||
outer:
|
outer:
|
||||||
for(int x = quadrantX * quadrantSize; x < world.width() && x < (quadrantX + 1) * quadrantSize; x++){
|
for(int x = quadrantX * quadrantSize; x < world.width() && x < (quadrantX + 1) * quadrantSize; x++){
|
||||||
@@ -299,7 +320,7 @@ public class BlockIndexer{
|
|||||||
Tile result = world.ltile(x, y);
|
Tile result = world.ltile(x, y);
|
||||||
//when a targetable block is found, mark this quadrant as occupied and stop searching
|
//when a targetable block is found, mark this quadrant as occupied and stop searching
|
||||||
if(result.entity != null && result.getTeam() == data.team){
|
if(result.entity != null && result.getTeam() == data.team){
|
||||||
structQuadrants[data.team.ordinal()].set(quadrantX, quadrantY);
|
bits.set(quadrantX, quadrantY);
|
||||||
break outer;
|
break outer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -308,7 +329,7 @@ public class BlockIndexer{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean getQuad(Team team, int quadrantX, int quadrantY){
|
private boolean getQuad(Team team, int quadrantX, int quadrantY){
|
||||||
return structQuadrants[team.ordinal()].get(quadrantX, quadrantY);
|
return structQuadrant(team).get(quadrantX, quadrantY);
|
||||||
}
|
}
|
||||||
|
|
||||||
private int quadWidth(){
|
private int quadWidth(){
|
||||||
|
|||||||
@@ -27,9 +27,9 @@ public class Pathfinder implements Runnable{
|
|||||||
/** unordered array of path data for iteration only. DO NOT iterate ot access this in the main thread.*/
|
/** unordered array of path data for iteration only. DO NOT iterate ot access this in the main thread.*/
|
||||||
private Array<PathData> list = new Array<>();
|
private Array<PathData> list = new Array<>();
|
||||||
/** Maps teams + flags to a valid path to get to that flag for that team. */
|
/** Maps teams + flags to a valid path to get to that flag for that team. */
|
||||||
private PathData[][] pathMap = new PathData[Team.all.length][PathTarget.all.length];
|
private PathData[][] pathMap = new PathData[Team.all().length][PathTarget.all.length];
|
||||||
/** Grid map of created path data that should not be queued again. */
|
/** Grid map of created path data that should not be queued again. */
|
||||||
private GridBits created = new GridBits(Team.all.length, PathTarget.all.length);
|
private GridBits created = new GridBits(Team.all().length, PathTarget.all.length);
|
||||||
/** handles task scheduling on the update thread. */
|
/** handles task scheduling on the update thread. */
|
||||||
private TaskQueue queue = new TaskQueue();
|
private TaskQueue queue = new TaskQueue();
|
||||||
/** current pathfinding thread */
|
/** current pathfinding thread */
|
||||||
@@ -42,8 +42,8 @@ public class Pathfinder implements Runnable{
|
|||||||
|
|
||||||
//reset and update internal tile array
|
//reset and update internal tile array
|
||||||
tiles = new int[world.width()][world.height()];
|
tiles = new int[world.width()][world.height()];
|
||||||
pathMap = new PathData[Team.all.length][PathTarget.all.length];
|
pathMap = new PathData[Team.all().length][PathTarget.all.length];
|
||||||
created = new GridBits(Team.all.length, PathTarget.all.length);
|
created = new GridBits(Team.all().length, PathTarget.all.length);
|
||||||
list = new Array<>();
|
list = new Array<>();
|
||||||
|
|
||||||
for(int x = 0; x < world.width(); x++){
|
for(int x = 0; x < world.width(); x++){
|
||||||
@@ -53,7 +53,7 @@ public class Pathfinder implements Runnable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
//special preset which may help speed things up; this is optional
|
//special preset which may help speed things up; this is optional
|
||||||
preloadPath(waveTeam, PathTarget.enemyCores);
|
preloadPath(state.rules.waveTeam, PathTarget.enemyCores);
|
||||||
|
|
||||||
start();
|
start();
|
||||||
});
|
});
|
||||||
@@ -84,8 +84,8 @@ public class Pathfinder implements Runnable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int debugValue(Team team, int x, int y){
|
public int debugValue(Team team, int x, int y){
|
||||||
if(pathMap[team.ordinal()][PathTarget.enemyCores.ordinal()] == null) return 0;
|
if(pathMap[team.id][PathTarget.enemyCores.ordinal()] == null) return 0;
|
||||||
return pathMap[team.ordinal()][PathTarget.enemyCores.ordinal()].weights[x][y];
|
return pathMap[team.id][PathTarget.enemyCores.ordinal()].weights[x][y];
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Update a tile in the internal pathfinding grid. Causes a complete pathfinding reclaculation. */
|
/** Update a tile in the internal pathfinding grid. Causes a complete pathfinding reclaculation. */
|
||||||
@@ -149,12 +149,12 @@ public class Pathfinder implements Runnable{
|
|||||||
public Tile getTargetTile(Tile tile, Team team, PathTarget target){
|
public Tile getTargetTile(Tile tile, Team team, PathTarget target){
|
||||||
if(tile == null) return null;
|
if(tile == null) return null;
|
||||||
|
|
||||||
PathData data = pathMap[team.ordinal()][target.ordinal()];
|
PathData data = pathMap[team.id][target.ordinal()];
|
||||||
|
|
||||||
if(data == null){
|
if(data == null){
|
||||||
//if this combination is not found, create it on request
|
//if this combination is not found, create it on request
|
||||||
if(!created.get(team.ordinal(), target.ordinal())){
|
if(!created.get(team.id, target.ordinal())){
|
||||||
created.set(team.ordinal(), target.ordinal());
|
created.set(team.id, target.ordinal());
|
||||||
//grab targets since this is run on main thread
|
//grab targets since this is run on main thread
|
||||||
IntArray targets = target.getTargets(team, new IntArray());
|
IntArray targets = target.getTargets(team, new IntArray());
|
||||||
queue.post(() -> createPath(team, target, targets));
|
queue.post(() -> createPath(team, target, targets));
|
||||||
@@ -188,7 +188,7 @@ public class Pathfinder implements Runnable{
|
|||||||
/** @return whether a tile can be passed through by this team. Pathfinding thread only.*/
|
/** @return whether a tile can be passed through by this team. Pathfinding thread only.*/
|
||||||
private boolean passable(int x, int y, Team team){
|
private boolean passable(int x, int y, Team team){
|
||||||
int tile = tiles[x][y];
|
int tile = tiles[x][y];
|
||||||
return PathTile.passable(tile) || (PathTile.team(tile) != team.ordinal() && PathTile.team(tile) != Team.derelict.ordinal());
|
return PathTile.passable(tile) || (PathTile.team(tile) != team.id && PathTile.team(tile) != (int)Team.derelict.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -238,7 +238,7 @@ public class Pathfinder implements Runnable{
|
|||||||
PathData path = new PathData(team, target, world.width(), world.height());
|
PathData path = new PathData(team, target, world.width(), world.height());
|
||||||
|
|
||||||
list.add(path);
|
list.add(path);
|
||||||
pathMap[team.ordinal()][target.ordinal()] = path;
|
pathMap[team.id][target.ordinal()] = path;
|
||||||
|
|
||||||
//grab targets from passed array
|
//grab targets from passed array
|
||||||
synchronized(path.targets){
|
synchronized(path.targets){
|
||||||
@@ -303,7 +303,7 @@ public class Pathfinder implements Runnable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
//spawn points are also enemies.
|
//spawn points are also enemies.
|
||||||
if(state.rules.waves && team == defaultTeam){
|
if(state.rules.waves && team == state.rules.defaultTeam){
|
||||||
for(Tile other : spawner.getGroundSpawns()){
|
for(Tile other : spawner.getGroundSpawns()){
|
||||||
out.add(other.pos());
|
out.add(other.pos());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import mindustry.content.Blocks;
|
|||||||
import mindustry.content.Fx;
|
import mindustry.content.Fx;
|
||||||
import mindustry.entities.Damage;
|
import mindustry.entities.Damage;
|
||||||
import mindustry.entities.Effects;
|
import mindustry.entities.Effects;
|
||||||
import mindustry.entities.type.BaseUnit;
|
import mindustry.entities.type.*;
|
||||||
import mindustry.game.EventType.WorldLoadEvent;
|
import mindustry.game.EventType.WorldLoadEvent;
|
||||||
import mindustry.game.SpawnGroup;
|
import mindustry.game.SpawnGroup;
|
||||||
import mindustry.world.Tile;
|
import mindustry.world.Tile;
|
||||||
@@ -53,7 +53,7 @@ public class WaveSpawner{
|
|||||||
|
|
||||||
eachFlyerSpawn((spawnX, spawnY) -> {
|
eachFlyerSpawn((spawnX, spawnY) -> {
|
||||||
for(int i = 0; i < spawned; i++){
|
for(int i = 0; i < spawned; i++){
|
||||||
BaseUnit unit = group.createUnit(waveTeam);
|
BaseUnit unit = group.createUnit(state.rules.waveTeam);
|
||||||
unit.set(spawnX + Mathf.range(spread), spawnY + Mathf.range(spread));
|
unit.set(spawnX + Mathf.range(spread), spawnY + Mathf.range(spread));
|
||||||
unit.add();
|
unit.add();
|
||||||
}
|
}
|
||||||
@@ -66,7 +66,7 @@ public class WaveSpawner{
|
|||||||
for(int i = 0; i < spawned; i++){
|
for(int i = 0; i < spawned; i++){
|
||||||
Tmp.v1.rnd(spread);
|
Tmp.v1.rnd(spread);
|
||||||
|
|
||||||
BaseUnit unit = group.createUnit(waveTeam);
|
BaseUnit unit = group.createUnit(state.rules.waveTeam);
|
||||||
unit.set(spawnX + Tmp.v1.x, spawnY + Tmp.v1.y);
|
unit.set(spawnX + Tmp.v1.x, spawnY + Tmp.v1.y);
|
||||||
|
|
||||||
Time.run(Math.min(i * 5, 60 * 2), () -> spawnEffect(unit));
|
Time.run(Math.min(i * 5, 60 * 2), () -> spawnEffect(unit));
|
||||||
@@ -78,7 +78,7 @@ public class WaveSpawner{
|
|||||||
eachGroundSpawn((spawnX, spawnY, doShockwave) -> {
|
eachGroundSpawn((spawnX, spawnY, doShockwave) -> {
|
||||||
if(doShockwave){
|
if(doShockwave){
|
||||||
Time.run(20f, () -> Effects.effect(Fx.spawnShockwave, spawnX, spawnY, state.rules.dropZoneRadius));
|
Time.run(20f, () -> Effects.effect(Fx.spawnShockwave, spawnX, spawnY, state.rules.dropZoneRadius));
|
||||||
Time.run(40f, () -> Damage.damage(waveTeam, spawnX, spawnY, state.rules.dropZoneRadius, 99999999f, true));
|
Time.run(40f, () -> Damage.damage(state.rules.waveTeam, spawnX, spawnY, state.rules.dropZoneRadius, 99999999f, true));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -90,11 +90,11 @@ public class WaveSpawner{
|
|||||||
cons.accept(spawn.worldx(), spawn.worldy(), true);
|
cons.accept(spawn.worldx(), spawn.worldy(), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(state.rules.attackMode && state.teams.isActive(waveTeam) && !state.teams.get(defaultTeam).cores.isEmpty()){
|
if(state.rules.attackMode && state.teams.isActive(state.rules.waveTeam) && !state.teams.playerCores().isEmpty()){
|
||||||
Tile firstCore = state.teams.get(defaultTeam).cores.first();
|
TileEntity firstCore = state.teams.playerCores().first();
|
||||||
for(Tile core : state.teams.get(waveTeam).cores){
|
for(TileEntity core : state.rules.waveTeam.cores()){
|
||||||
Tmp.v1.set(firstCore).sub(core.worldx(), core.worldy()).limit(coreMargin + core.block().size*tilesize);
|
Tmp.v1.set(firstCore).sub(core.x, core.y).limit(coreMargin + core.block.size*tilesize);
|
||||||
cons.accept(core.worldx() + Tmp.v1.x, core.worldy() + Tmp.v1.y, false);
|
cons.accept(core.x + Tmp.v1.x, core.y + Tmp.v1.y, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -107,9 +107,9 @@ public class WaveSpawner{
|
|||||||
cons.get(spawnX, spawnY);
|
cons.get(spawnX, spawnY);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(state.rules.attackMode && state.teams.isActive(waveTeam)){
|
if(state.rules.attackMode && state.teams.isActive(state.rules.waveTeam)){
|
||||||
for(Tile core : state.teams.get(waveTeam).cores){
|
for(TileEntity core : state.teams.get(state.rules.waveTeam).cores){
|
||||||
cons.get(core.worldx(), core.worldy());
|
cons.get(core.x, core.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1079,6 +1079,7 @@ public class Fx implements ContentList{
|
|||||||
healBlockFull = new Effect(20, e -> {
|
healBlockFull = new Effect(20, e -> {
|
||||||
Draw.color(e.color);
|
Draw.color(e.color);
|
||||||
Draw.alpha(e.fout());
|
Draw.alpha(e.fout());
|
||||||
|
Fill.square(e.x, e.y, e.rotation * tilesize / 2f);
|
||||||
});
|
});
|
||||||
|
|
||||||
overdriveBlockFull = new Effect(60, e -> {
|
overdriveBlockFull = new Effect(60, e -> {
|
||||||
|
|||||||
@@ -6,8 +6,7 @@ import mindustry.entities.Effects;
|
|||||||
import mindustry.ctype.ContentList;
|
import mindustry.ctype.ContentList;
|
||||||
import mindustry.game.EventType.*;
|
import mindustry.game.EventType.*;
|
||||||
import mindustry.type.StatusEffect;
|
import mindustry.type.StatusEffect;
|
||||||
|
import static mindustry.Vars.*;
|
||||||
import static mindustry.Vars.waveTeam;
|
|
||||||
|
|
||||||
public class StatusEffects implements ContentList{
|
public class StatusEffects implements ContentList{
|
||||||
public static StatusEffect none, burning, freezing, wet, melting, tarred, overdrive, shielded, shocked, corroded, boss;
|
public static StatusEffect none, burning, freezing, wet, melting, tarred, overdrive, shielded, shocked, corroded, boss;
|
||||||
@@ -48,7 +47,7 @@ public class StatusEffects implements ContentList{
|
|||||||
init(() -> {
|
init(() -> {
|
||||||
trans(shocked, ((unit, time, newTime, result) -> {
|
trans(shocked, ((unit, time, newTime, result) -> {
|
||||||
unit.damage(20f);
|
unit.damage(20f);
|
||||||
if(unit.getTeam() == waveTeam){
|
if(unit.getTeam() == state.rules.waveTeam){
|
||||||
Events.fire(Trigger.shock);
|
Events.fire(Trigger.shock);
|
||||||
}
|
}
|
||||||
result.set(this, time);
|
result.set(this, time);
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ public class Control implements ApplicationListener, Loadable{
|
|||||||
});
|
});
|
||||||
|
|
||||||
Events.on(PlayEvent.class, event -> {
|
Events.on(PlayEvent.class, event -> {
|
||||||
player.setTeam(state.rules.pvp ? netServer.assignTeam(player, playerGroup.all()) : defaultTeam);
|
player.setTeam(netServer.assignTeam(player, playerGroup.all()));
|
||||||
player.setDead(true);
|
player.setDead(true);
|
||||||
player.add();
|
player.add();
|
||||||
|
|
||||||
@@ -256,9 +256,9 @@ public class Control implements ApplicationListener, Loadable{
|
|||||||
world.loadGenerator(zone.generator);
|
world.loadGenerator(zone.generator);
|
||||||
zone.rules.get(state.rules);
|
zone.rules.get(state.rules);
|
||||||
state.rules.zone = zone;
|
state.rules.zone = zone;
|
||||||
for(Tile core : state.teams.get(defaultTeam).cores){
|
for(TileEntity core : state.teams.playerCores()){
|
||||||
for(ItemStack stack : zone.getStartingItems()){
|
for(ItemStack stack : zone.getStartingItems()){
|
||||||
core.entity.items.add(stack.item, stack.amount);
|
core.items.add(stack.item, stack.amount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state.set(State.playing);
|
state.set(State.playing);
|
||||||
@@ -294,8 +294,8 @@ public class Control implements ApplicationListener, Loadable{
|
|||||||
|
|
||||||
Geometry.circle(coreb.x, coreb.y, 10, (cx, cy) -> {
|
Geometry.circle(coreb.x, coreb.y, 10, (cx, cy) -> {
|
||||||
Tile tile = world.ltile(cx, cy);
|
Tile tile = world.ltile(cx, cy);
|
||||||
if(tile != null && tile.getTeam() == defaultTeam && !(tile.block() instanceof CoreBlock)){
|
if(tile != null && tile.getTeam() == state.rules.defaultTeam && !(tile.block() instanceof CoreBlock)){
|
||||||
world.removeBlock(tile);
|
tile.remove();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -305,13 +305,13 @@ public class Control implements ApplicationListener, Loadable{
|
|||||||
|
|
||||||
zone.rules.get(state.rules);
|
zone.rules.get(state.rules);
|
||||||
state.rules.zone = zone;
|
state.rules.zone = zone;
|
||||||
for(Tile core : state.teams.get(defaultTeam).cores){
|
for(TileEntity core : state.teams.playerCores()){
|
||||||
for(ItemStack stack : zone.getStartingItems()){
|
for(ItemStack stack : zone.getStartingItems()){
|
||||||
core.entity.items.add(stack.item, stack.amount);
|
core.items.add(stack.item, stack.amount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Tile core = state.teams.get(defaultTeam).cores.first();
|
TileEntity core = state.teams.playerCores().first();
|
||||||
core.entity.items.clear();
|
core.items.clear();
|
||||||
|
|
||||||
logic.play();
|
logic.play();
|
||||||
state.rules.waveTimer = false;
|
state.rules.waveTimer = false;
|
||||||
@@ -434,9 +434,9 @@ public class Control implements ApplicationListener, Loadable{
|
|||||||
input.update();
|
input.update();
|
||||||
|
|
||||||
if(world.isZone()){
|
if(world.isZone()){
|
||||||
for(Tile tile : state.teams.get(player.getTeam()).cores){
|
for(TileEntity tile : state.teams.cores(player.getTeam())){
|
||||||
for(Item item : content.items()){
|
for(Item item : content.items()){
|
||||||
if(tile.entity != null && tile.entity.items.has(item)){
|
if(tile.items.has(item)){
|
||||||
data.unlockContent(item);
|
data.unlockContent(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package mindustry.core;
|
|||||||
|
|
||||||
import arc.*;
|
import arc.*;
|
||||||
import mindustry.entities.type.*;
|
import mindustry.entities.type.*;
|
||||||
import mindustry.entities.type.base.*;
|
|
||||||
import mindustry.game.EventType.*;
|
import mindustry.game.EventType.*;
|
||||||
import mindustry.game.*;
|
import mindustry.game.*;
|
||||||
|
|
||||||
@@ -26,12 +25,8 @@ public class GameState{
|
|||||||
/** Current game state. */
|
/** Current game state. */
|
||||||
private State state = State.menu;
|
private State state = State.menu;
|
||||||
|
|
||||||
public int enemies(){
|
|
||||||
return net.client() ? enemies : unitGroups[waveTeam.ordinal()].count(b -> !(b instanceof BaseDrone));
|
|
||||||
}
|
|
||||||
|
|
||||||
public BaseUnit boss(){
|
public BaseUnit boss(){
|
||||||
return unitGroups[waveTeam.ordinal()].find(BaseUnit::isBoss);
|
return unitGroup.find(u -> u.isBoss() && u.getTeam() == rules.waveTeam);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set(State astate){
|
public void set(State astate){
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package mindustry.core;
|
package mindustry.core;
|
||||||
|
|
||||||
import arc.*;
|
import arc.*;
|
||||||
import mindustry.annotations.Annotations.*;
|
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
import mindustry.content.*;
|
import mindustry.content.*;
|
||||||
import mindustry.core.GameState.*;
|
import mindustry.core.GameState.*;
|
||||||
import mindustry.ctype.*;
|
import mindustry.ctype.*;
|
||||||
@@ -107,9 +107,9 @@ public class Logic implements ApplicationListener{
|
|||||||
|
|
||||||
//add starting items
|
//add starting items
|
||||||
if(!world.isZone()){
|
if(!world.isZone()){
|
||||||
for(Team team : Team.all){
|
for(TeamData team : state.teams.getActive()){
|
||||||
if(!state.teams.get(team).cores.isEmpty()){
|
if(team.hasCore()){
|
||||||
TileEntity entity = state.teams.get(team).cores.first().entity;
|
TileEntity entity = team.core();
|
||||||
entity.items.clear();
|
entity.items.clear();
|
||||||
for(ItemStack stack : state.rules.loadout){
|
for(ItemStack stack : state.rules.loadout){
|
||||||
entity.items.add(stack.item, stack.amount);
|
entity.items.add(stack.item, stack.amount);
|
||||||
@@ -143,23 +143,23 @@ public class Logic implements ApplicationListener{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void checkGameOver(){
|
private void checkGameOver(){
|
||||||
if(!state.rules.attackMode && state.teams.get(defaultTeam).cores.size == 0 && !state.gameOver){
|
if(!state.rules.attackMode && state.teams.playerCores().size == 0 && !state.gameOver){
|
||||||
state.gameOver = true;
|
state.gameOver = true;
|
||||||
Events.fire(new GameOverEvent(waveTeam));
|
Events.fire(new GameOverEvent(state.rules.waveTeam));
|
||||||
}else if(state.rules.attackMode){
|
}else if(state.rules.attackMode){
|
||||||
Team alive = null;
|
Team alive = null;
|
||||||
|
|
||||||
for(Team team : Team.all){
|
for(TeamData team : state.teams.getActive()){
|
||||||
if(state.teams.get(team).cores.size > 0){
|
if(team.hasCore()){
|
||||||
if(alive != null){
|
if(alive != null){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
alive = team;
|
alive = team.team;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(alive != null && !state.gameOver){
|
if(alive != null && !state.gameOver){
|
||||||
if(world.isZone() && alive == defaultTeam){
|
if(world.isZone() && alive == state.rules.defaultTeam){
|
||||||
//in attack maps, a victorious game over is equivalent to a launch
|
//in attack maps, a victorious game over is equivalent to a launch
|
||||||
Call.launchZone();
|
Call.launchZone();
|
||||||
}else{
|
}else{
|
||||||
@@ -176,7 +176,7 @@ public class Logic implements ApplicationListener{
|
|||||||
ui.hudfrag.showLaunch();
|
ui.hudfrag.showLaunch();
|
||||||
}
|
}
|
||||||
|
|
||||||
for(Tile tile : state.teams.get(defaultTeam).cores){
|
for(TileEntity tile : state.teams.playerCores()){
|
||||||
Effects.effect(Fx.launch, tile);
|
Effects.effect(Fx.launch, tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,19 +185,18 @@ public class Logic implements ApplicationListener{
|
|||||||
}
|
}
|
||||||
|
|
||||||
Time.runTask(30f, () -> {
|
Time.runTask(30f, () -> {
|
||||||
for(Tile tile : state.teams.get(defaultTeam).cores){
|
for(TileEntity entity : state.teams.playerCores()){
|
||||||
for(Item item : content.items()){
|
for(Item item : content.items()){
|
||||||
if(tile == null || tile.entity == null || tile.entity.items == null) continue;
|
data.addItem(item, entity.items.get(item));
|
||||||
data.addItem(item, tile.entity.items.get(item));
|
Events.fire(new LaunchItemEvent(item, entity.items.get(item)));
|
||||||
Events.fire(new LaunchItemEvent(item, tile.entity.items.get(item)));
|
|
||||||
}
|
}
|
||||||
world.removeBlock(tile);
|
entity.tile.remove();
|
||||||
}
|
}
|
||||||
state.launched = true;
|
state.launched = true;
|
||||||
state.gameOver = true;
|
state.gameOver = true;
|
||||||
Events.fire(new LaunchEvent());
|
Events.fire(new LaunchEvent());
|
||||||
//manually fire game over event now
|
//manually fire game over event now
|
||||||
Events.fire(new GameOverEvent(defaultTeam));
|
Events.fire(new GameOverEvent(state.rules.defaultTeam));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,12 +211,15 @@ public class Logic implements ApplicationListener{
|
|||||||
public void update(){
|
public void update(){
|
||||||
|
|
||||||
if(!state.is(State.menu)){
|
if(!state.is(State.menu)){
|
||||||
|
if(!net.client()){
|
||||||
|
state.enemies = unitGroup.count(b -> b.getTeam() == state.rules.waveTeam && b.countsAsEnemy());
|
||||||
|
}
|
||||||
|
|
||||||
if(!state.isPaused()){
|
if(!state.isPaused()){
|
||||||
Time.update();
|
Time.update();
|
||||||
|
|
||||||
if(state.rules.waves && state.rules.waveTimer && !state.gameOver){
|
if(state.rules.waves && state.rules.waveTimer && !state.gameOver){
|
||||||
if(!state.rules.waitForWaveToEnd || unitGroups[waveTeam.ordinal()].size() == 0){
|
if(!state.rules.waitForWaveToEnd || state.enemies == 0){
|
||||||
state.wavetime = Math.max(state.wavetime - Time.delta(), 0);
|
state.wavetime = Math.max(state.wavetime - Time.delta(), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -232,20 +234,15 @@ public class Logic implements ApplicationListener{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!state.isEditor()){
|
if(!state.isEditor()){
|
||||||
for(EntityGroup group : unitGroups){
|
unitGroup.update();
|
||||||
group.update();
|
|
||||||
}
|
|
||||||
|
|
||||||
puddleGroup.update();
|
puddleGroup.update();
|
||||||
shieldGroup.update();
|
shieldGroup.update();
|
||||||
bulletGroup.update();
|
bulletGroup.update();
|
||||||
tileGroup.update();
|
tileGroup.update();
|
||||||
fireGroup.update();
|
fireGroup.update();
|
||||||
}else{
|
}else{
|
||||||
for(EntityGroup<?> group : unitGroups){
|
unitGroup.updateEvents();
|
||||||
group.updateEvents();
|
collisions.updatePhysics(unitGroup);
|
||||||
collisions.updatePhysics(group);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -257,12 +254,8 @@ public class Logic implements ApplicationListener{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!state.isEditor()){
|
if(!state.isEditor()){
|
||||||
|
//bulletGroup
|
||||||
for(EntityGroup group : unitGroups){
|
collisions.collideGroups(bulletGroup, unitGroup);
|
||||||
if(group.isEmpty()) continue;
|
|
||||||
collisions.collideGroups(bulletGroup, group);
|
|
||||||
}
|
|
||||||
|
|
||||||
collisions.collideGroups(bulletGroup, playerGroup);
|
collisions.collideGroups(bulletGroup, playerGroup);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -160,9 +160,17 @@ public class NetClient implements ApplicationListener{
|
|||||||
throw new ValidateException(player, "Player has sent a message above the text limit.");
|
throw new ValidateException(player, "Player has sent a message above the text limit.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String original = message;
|
||||||
|
|
||||||
//check if it's a command
|
//check if it's a command
|
||||||
CommandResponse response = netServer.clientCommands.handleMessage(message, player);
|
CommandResponse response = netServer.clientCommands.handleMessage(message, player);
|
||||||
if(response.type == ResponseType.noCommand){ //no command to handle
|
if(response.type == ResponseType.noCommand){ //no command to handle
|
||||||
|
message = netServer.admins.filterMessage(player, message);
|
||||||
|
//supress chat message if it's filtered out
|
||||||
|
if(message == null){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//server console logging
|
//server console logging
|
||||||
Log.info("&y{0}: &lb{1}", player.name, message);
|
Log.info("&y{0}: &lb{1}", player.name, message);
|
||||||
|
|
||||||
@@ -190,7 +198,7 @@ public class NetClient implements ApplicationListener{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Events.fire(new PlayerChatEvent(player, message));
|
Events.fire(new PlayerChatEvent(player, message, original));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String colorizeName(int id, String name){
|
public static String colorizeName(int id, String name){
|
||||||
|
|||||||
@@ -17,11 +17,13 @@ import mindustry.entities.traits.*;
|
|||||||
import mindustry.entities.type.*;
|
import mindustry.entities.type.*;
|
||||||
import mindustry.game.EventType.*;
|
import mindustry.game.EventType.*;
|
||||||
import mindustry.game.*;
|
import mindustry.game.*;
|
||||||
|
import mindustry.game.Teams.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.net.*;
|
import mindustry.net.*;
|
||||||
import mindustry.net.Administration.*;
|
import mindustry.net.Administration.*;
|
||||||
import mindustry.net.Packets.*;
|
import mindustry.net.Packets.*;
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
|
import mindustry.world.blocks.storage.CoreBlock.*;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.nio.*;
|
import java.nio.*;
|
||||||
@@ -31,14 +33,31 @@ import static mindustry.Vars.*;
|
|||||||
|
|
||||||
public class NetServer implements ApplicationListener{
|
public class NetServer implements ApplicationListener{
|
||||||
private final static int maxSnapshotSize = 430, timerBlockSync = 0;
|
private final static int maxSnapshotSize = 430, timerBlockSync = 0;
|
||||||
private final static float serverSyncTime = 12, kickDuration = 30 * 1000, blockSyncTime = 60 * 10;
|
private final static float serverSyncTime = 12, kickDuration = 30 * 1000, blockSyncTime = 60 * 8;
|
||||||
private final static Vec2 vector = new Vec2();
|
private final static Vec2 vector = new Vec2();
|
||||||
private final static Rectangle viewport = new Rectangle();
|
private final static Rect viewport = new Rect();
|
||||||
/** If a player goes away of their server-side coordinates by this distance, they get teleported back. */
|
/** If a player goes away of their server-side coordinates by this distance, they get teleported back. */
|
||||||
private final static float correctDist = 16f;
|
private final static float correctDist = 16f;
|
||||||
|
|
||||||
public final Administration admins = new Administration();
|
public final Administration admins = new Administration();
|
||||||
public final CommandHandler clientCommands = new CommandHandler("/");
|
public final CommandHandler clientCommands = new CommandHandler("/");
|
||||||
|
public TeamAssigner assigner = (player, players) -> {
|
||||||
|
if(state.rules.pvp){
|
||||||
|
//find team with minimum amount of players and auto-assign player to that.
|
||||||
|
TeamData re = state.teams.getActive().min(data -> {
|
||||||
|
int count = 0;
|
||||||
|
for(Player other : players){
|
||||||
|
if(other.getTeam() == data.team && other != player){
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
});
|
||||||
|
return re == null ? null : re.team;
|
||||||
|
}
|
||||||
|
|
||||||
|
return state.rules.defaultTeam;
|
||||||
|
};
|
||||||
|
|
||||||
private boolean closing = false;
|
private boolean closing = false;
|
||||||
private Interval timer = new Interval();
|
private Interval timer = new Interval();
|
||||||
@@ -197,10 +216,8 @@ public class NetServer implements ApplicationListener{
|
|||||||
con.player = player;
|
con.player = player;
|
||||||
|
|
||||||
//playing in pvp mode automatically assigns players to teams
|
//playing in pvp mode automatically assigns players to teams
|
||||||
if(state.rules.pvp){
|
player.setTeam(assignTeam(player, playerGroup.all()));
|
||||||
player.setTeam(assignTeam(player, playerGroup.all()));
|
Log.info("Auto-assigned player {0} to team {1}.", player.name, player.getTeam());
|
||||||
Log.info("Auto-assigned player {0} to team {1}.", player.name, player.getTeam());
|
|
||||||
}
|
|
||||||
|
|
||||||
sendWorldData(player);
|
sendWorldData(player);
|
||||||
|
|
||||||
@@ -401,19 +418,7 @@ public class NetServer implements ApplicationListener{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Team assignTeam(Player current, Iterable<Player> players){
|
public Team assignTeam(Player current, Iterable<Player> players){
|
||||||
//find team with minimum amount of players and auto-assign player to that.
|
return assigner.assign(current, players);
|
||||||
return Structs.findMin(Team.all, team -> {
|
|
||||||
if(state.teams.isActive(team) && !state.teams.get(team).cores.isEmpty()){
|
|
||||||
int count = 0;
|
|
||||||
for(Player other : players){
|
|
||||||
if(other.getTeam() == team && other != current){
|
|
||||||
count++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
return Integer.MAX_VALUE;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendWorldData(Player player){
|
public void sendWorldData(Player player){
|
||||||
@@ -584,8 +589,8 @@ public class NetServer implements ApplicationListener{
|
|||||||
public boolean isWaitingForPlayers(){
|
public boolean isWaitingForPlayers(){
|
||||||
if(state.rules.pvp){
|
if(state.rules.pvp){
|
||||||
int used = 0;
|
int used = 0;
|
||||||
for(Team t : Team.all){
|
for(TeamData t : state.teams.getActive()){
|
||||||
if(playerGroup.count(p -> p.getTeam() == t) > 0){
|
if(playerGroup.count(p -> p.getTeam() == t.team) > 0){
|
||||||
used++;
|
used++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -647,20 +652,20 @@ public class NetServer implements ApplicationListener{
|
|||||||
|
|
||||||
public void writeEntitySnapshot(Player player) throws IOException{
|
public void writeEntitySnapshot(Player player) throws IOException{
|
||||||
syncStream.reset();
|
syncStream.reset();
|
||||||
ObjectSet<Tile> cores = state.teams.get(player.getTeam()).cores;
|
Array<CoreEntity> cores = state.teams.cores(player.getTeam());
|
||||||
|
|
||||||
dataStream.writeByte(cores.size);
|
dataStream.writeByte(cores.size);
|
||||||
|
|
||||||
for(Tile tile : cores){
|
for(CoreEntity entity : cores){
|
||||||
dataStream.writeInt(tile.pos());
|
dataStream.writeInt(entity.tile.pos());
|
||||||
tile.entity.items.write(dataStream);
|
entity.items.write(dataStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
dataStream.close();
|
dataStream.close();
|
||||||
byte[] stateBytes = syncStream.toByteArray();
|
byte[] stateBytes = syncStream.toByteArray();
|
||||||
|
|
||||||
//write basic state data.
|
//write basic state data.
|
||||||
Call.onStateSnapshot(player.con, state.wavetime, state.wave, state.enemies(), (short)stateBytes.length, net.compressSnapshot(stateBytes));
|
Call.onStateSnapshot(player.con, state.wavetime, state.wave, state.enemies, (short)stateBytes.length, net.compressSnapshot(stateBytes));
|
||||||
|
|
||||||
viewport.setSize(player.con.viewWidth, player.con.viewHeight).setCenter(player.con.viewX, player.con.viewY);
|
viewport.setSize(player.con.viewWidth, player.con.viewHeight).setCenter(player.con.viewX, player.con.viewY);
|
||||||
|
|
||||||
@@ -784,4 +789,8 @@ public class NetServer implements ApplicationListener{
|
|||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface TeamAssigner{
|
||||||
|
Team assign(Player player, Iterable<Player> players);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,11 +18,10 @@ import mindustry.entities.effect.*;
|
|||||||
import mindustry.entities.effect.GroundEffectEntity.*;
|
import mindustry.entities.effect.GroundEffectEntity.*;
|
||||||
import mindustry.entities.traits.*;
|
import mindustry.entities.traits.*;
|
||||||
import mindustry.entities.type.*;
|
import mindustry.entities.type.*;
|
||||||
import mindustry.game.*;
|
|
||||||
import mindustry.game.EventType.*;
|
import mindustry.game.EventType.*;
|
||||||
import mindustry.graphics.*;
|
import mindustry.graphics.*;
|
||||||
import mindustry.input.*;
|
import mindustry.input.*;
|
||||||
import mindustry.ui.Cicon;
|
import mindustry.ui.*;
|
||||||
import mindustry.world.blocks.defense.ForceProjector.*;
|
import mindustry.world.blocks.defense.ForceProjector.*;
|
||||||
|
|
||||||
import static arc.Core.*;
|
import static arc.Core.*;
|
||||||
@@ -42,7 +41,7 @@ public class Renderer implements ApplicationListener{
|
|||||||
private float camerascale = targetscale;
|
private float camerascale = targetscale;
|
||||||
private float landscale = 0f, landTime;
|
private float landscale = 0f, landTime;
|
||||||
private float minZoomScl = Scl.scl(0.01f);
|
private float minZoomScl = Scl.scl(0.01f);
|
||||||
private Rectangle rect = new Rectangle(), rect2 = new Rectangle();
|
private Rect rect = new Rect(), rect2 = new Rect();
|
||||||
private float shakeIntensity, shaketime;
|
private float shakeIntensity, shaketime;
|
||||||
|
|
||||||
public Renderer(){
|
public Renderer(){
|
||||||
@@ -57,8 +56,8 @@ public class Renderer implements ApplicationListener{
|
|||||||
Effects.setEffectProvider((effect, color, x, y, rotation, data) -> {
|
Effects.setEffectProvider((effect, color, x, y, rotation, data) -> {
|
||||||
if(effect == Fx.none) return;
|
if(effect == Fx.none) return;
|
||||||
if(Core.settings.getBool("effects")){
|
if(Core.settings.getBool("effects")){
|
||||||
Rectangle view = camera.bounds(rect);
|
Rect view = camera.bounds(rect);
|
||||||
Rectangle pos = rect2.setSize(effect.size).setCenter(x, y);
|
Rect pos = rect2.setSize(effect.size).setCenter(x, y);
|
||||||
|
|
||||||
if(view.overlaps(pos)){
|
if(view.overlaps(pos)){
|
||||||
|
|
||||||
@@ -344,11 +343,7 @@ public class Renderer implements ApplicationListener{
|
|||||||
Draw.rect("circle-shadow", u.x, u.y, size * rad, size * rad);
|
Draw.rect("circle-shadow", u.x, u.y, size * rad, size * rad);
|
||||||
};
|
};
|
||||||
|
|
||||||
for(EntityGroup<? extends BaseUnit> group : unitGroups){
|
unitGroup.draw(unit -> !unit.isDead(), draw::get);
|
||||||
if(!group.isEmpty()){
|
|
||||||
group.draw(unit -> !unit.isDead(), draw::get);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!playerGroup.isEmpty()){
|
if(!playerGroup.isEmpty()){
|
||||||
playerGroup.draw(unit -> !unit.isDead(), draw::get);
|
playerGroup.draw(unit -> !unit.isDead(), draw::get);
|
||||||
@@ -361,34 +356,21 @@ public class Renderer implements ApplicationListener{
|
|||||||
float trnsX = -12, trnsY = -13;
|
float trnsX = -12, trnsY = -13;
|
||||||
Draw.color(0, 0, 0, 0.22f);
|
Draw.color(0, 0, 0, 0.22f);
|
||||||
|
|
||||||
for(EntityGroup<? extends BaseUnit> group : unitGroups){
|
unitGroup.draw(unit -> unit.isFlying() && !unit.isDead(), baseUnit -> baseUnit.drawShadow(trnsX, trnsY));
|
||||||
if(!group.isEmpty()){
|
playerGroup.draw(unit -> unit.isFlying() && !unit.isDead(), player -> player.drawShadow(trnsX, trnsY));
|
||||||
group.draw(unit -> unit.isFlying() && !unit.isDead(), baseUnit -> baseUnit.drawShadow(trnsX, trnsY));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!playerGroup.isEmpty()){
|
|
||||||
playerGroup.draw(unit -> unit.isFlying() && !unit.isDead(), player -> player.drawShadow(trnsX, trnsY));
|
|
||||||
}
|
|
||||||
|
|
||||||
Draw.color();
|
Draw.color();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawAllTeams(boolean flying){
|
private void drawAllTeams(boolean flying){
|
||||||
for(Team team : Team.all){
|
unitGroup.draw(u -> u.isFlying() == flying && !u.isDead(), Unit::drawUnder);
|
||||||
EntityGroup<BaseUnit> group = unitGroups[team.ordinal()];
|
playerGroup.draw(p -> p.isFlying() == flying && !p.isDead(), Unit::drawUnder);
|
||||||
|
|
||||||
if(group.count(p -> p.isFlying() == flying) + playerGroup.count(p -> p.isFlying() == flying && p.getTeam() == team) == 0 && flying) continue;
|
unitGroup.draw(u -> u.isFlying() == flying && !u.isDead(), Unit::drawAll);
|
||||||
|
playerGroup.draw(p -> p.isFlying() == flying, Unit::drawAll);
|
||||||
|
|
||||||
unitGroups[team.ordinal()].draw(u -> u.isFlying() == flying && !u.isDead(), Unit::drawUnder);
|
unitGroup.draw(u -> u.isFlying() == flying && !u.isDead(), Unit::drawOver);
|
||||||
playerGroup.draw(p -> p.isFlying() == flying && p.getTeam() == team && !p.isDead(), Unit::drawUnder);
|
playerGroup.draw(p -> p.isFlying() == flying, Unit::drawOver);
|
||||||
|
|
||||||
unitGroups[team.ordinal()].draw(u -> u.isFlying() == flying && !u.isDead(), Unit::drawAll);
|
|
||||||
playerGroup.draw(p -> p.isFlying() == flying && p.getTeam() == team, Unit::drawAll);
|
|
||||||
|
|
||||||
unitGroups[team.ordinal()].draw(u -> u.isFlying() == flying && !u.isDead(), Unit::drawOver);
|
|
||||||
playerGroup.draw(p -> p.isFlying() == flying && p.getTeam() == team, Unit::drawOver);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void scaleCamera(float amount){
|
public void scaleCamera(float amount){
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
package mindustry.core;
|
package mindustry.core;
|
||||||
|
|
||||||
import arc.*;
|
import arc.*;
|
||||||
import arc.struct.*;
|
|
||||||
import arc.math.*;
|
import arc.math.*;
|
||||||
import arc.math.geom.*;
|
import arc.math.geom.*;
|
||||||
import arc.util.*;
|
import arc.struct.*;
|
||||||
import arc.util.ArcAnnotate.*;
|
import arc.util.ArcAnnotate.*;
|
||||||
import mindustry.content.*;
|
import arc.util.*;
|
||||||
import mindustry.core.GameState.*;
|
import mindustry.core.GameState.*;
|
||||||
import mindustry.game.EventType.*;
|
import mindustry.game.EventType.*;
|
||||||
import mindustry.game.*;
|
import mindustry.game.*;
|
||||||
|
import mindustry.game.Teams.*;
|
||||||
import mindustry.io.*;
|
import mindustry.io.*;
|
||||||
import mindustry.maps.*;
|
import mindustry.maps.*;
|
||||||
import mindustry.maps.filters.*;
|
import mindustry.maps.filters.*;
|
||||||
@@ -233,33 +233,22 @@ public class World{
|
|||||||
invalidMap = false;
|
invalidMap = false;
|
||||||
|
|
||||||
if(!headless){
|
if(!headless){
|
||||||
if(state.teams.get(defaultTeam).cores.size == 0 && !checkRules.pvp){
|
if(state.teams.playerCores().size == 0 && !checkRules.pvp){
|
||||||
ui.showErrorMessage("$map.nospawn");
|
ui.showErrorMessage("$map.nospawn");
|
||||||
invalidMap = true;
|
invalidMap = true;
|
||||||
}else if(checkRules.pvp){ //pvp maps need two cores to be valid
|
}else if(checkRules.pvp){ //pvp maps need two cores to be valid
|
||||||
int teams = 0;
|
if(state.teams.getActive().count(TeamData::hasCore) < 2){
|
||||||
for(Team team : Team.all){
|
|
||||||
if(state.teams.get(team).cores.size != 0){
|
|
||||||
teams ++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(teams < 2){
|
|
||||||
invalidMap = true;
|
invalidMap = true;
|
||||||
ui.showErrorMessage("$map.nospawn.pvp");
|
ui.showErrorMessage("$map.nospawn.pvp");
|
||||||
}
|
}
|
||||||
}else if(checkRules.attackMode){ //attack maps need two cores to be valid
|
}else if(checkRules.attackMode){ //attack maps need two cores to be valid
|
||||||
invalidMap = state.teams.get(waveTeam).cores.isEmpty();
|
invalidMap = state.teams.get(state.rules.waveTeam).noCores();
|
||||||
if(invalidMap){
|
if(invalidMap){
|
||||||
ui.showErrorMessage("$map.nospawn.attack");
|
ui.showErrorMessage("$map.nospawn.attack");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}else{
|
}else{
|
||||||
invalidMap = true;
|
invalidMap = !state.teams.getActive().contains(TeamData::hasCore);
|
||||||
for(Team team : Team.all){
|
|
||||||
if(state.teams.get(team).cores.size != 0){
|
|
||||||
invalidMap = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(invalidMap){
|
if(invalidMap){
|
||||||
throw new MapException(map, "Map has no cores!");
|
throw new MapException(map, "Map has no cores!");
|
||||||
@@ -275,36 +264,6 @@ public class World{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeBlock(Tile tile){
|
|
||||||
if(tile == null) return;
|
|
||||||
tile.link().getLinkedTiles(other -> other.setBlock(Blocks.air));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBlock(Tile tile, Block block, Team team){
|
|
||||||
setBlock(tile, block, team, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBlock(Tile tile, Block block, Team team, int rotation){
|
|
||||||
tile.setBlock(block, team, rotation);
|
|
||||||
if(block.isMultiblock()){
|
|
||||||
int offsetx = -(block.size - 1) / 2;
|
|
||||||
int offsety = -(block.size - 1) / 2;
|
|
||||||
|
|
||||||
for(int dx = 0; dx < block.size; dx++){
|
|
||||||
for(int dy = 0; dy < block.size; dy++){
|
|
||||||
int worldx = dx + offsetx + tile.x;
|
|
||||||
int worldy = dy + offsety + tile.y;
|
|
||||||
if(!(worldx == tile.x && worldy == tile.y)){
|
|
||||||
Tile toplace = world.tile(worldx, worldy);
|
|
||||||
if(toplace != null){
|
|
||||||
toplace.setBlock(BlockPart.get(dx + offsetx, dy + offsety), team);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void raycastEachWorld(float x0, float y0, float x1, float y1, Raycaster cons){
|
public void raycastEachWorld(float x0, float y0, float x1, float y1, Raycaster cons){
|
||||||
raycastEach(toTile(x0), toTile(y0), toTile(x1), toTile(y1), cons);
|
raycastEach(toTile(x0), toTile(y0), toTile(x1), toTile(y1), cons);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ public class DrawOperation{
|
|||||||
}else if(type == OpType.rotation.ordinal()){
|
}else if(type == OpType.rotation.ordinal()){
|
||||||
tile.rotation(to);
|
tile.rotation(to);
|
||||||
}else if(type == OpType.team.ordinal()){
|
}else if(type == OpType.team.ordinal()){
|
||||||
tile.setTeam(Team.all[to]);
|
tile.setTeam(Team.get(to));
|
||||||
}else if(type == OpType.overlay.ordinal()){
|
}else if(type == OpType.overlay.ordinal()){
|
||||||
tile.setOverlayID(to);
|
tile.setOverlayID(to);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ public class EditorTile extends Tile{
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(getTeamID() == team.ordinal()) return;
|
if(getTeamID() == team.id) return;
|
||||||
op(OpType.team, getTeamID());
|
op(OpType.team, getTeamID());
|
||||||
super.setTeam(team);
|
super.setTeam(team);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
package mindustry.editor;
|
package mindustry.editor;
|
||||||
|
|
||||||
import arc.struct.IntArray;
|
|
||||||
import arc.func.*;
|
import arc.func.*;
|
||||||
import arc.math.Mathf;
|
import arc.math.*;
|
||||||
import arc.math.geom.Bresenham2;
|
import arc.math.geom.*;
|
||||||
import arc.util.Structs;
|
import arc.struct.*;
|
||||||
import mindustry.Vars;
|
import arc.util.*;
|
||||||
import mindustry.content.Blocks;
|
import mindustry.content.*;
|
||||||
import mindustry.game.Team;
|
import mindustry.game.*;
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
import mindustry.world.blocks.BlockPart;
|
import mindustry.world.blocks.*;
|
||||||
|
|
||||||
public enum EditorTool{
|
public enum EditorTool{
|
||||||
zoom,
|
zoom,
|
||||||
@@ -80,7 +79,7 @@ public enum EditorTool{
|
|||||||
editor.drawCircle(x, y, tile -> {
|
editor.drawCircle(x, y, tile -> {
|
||||||
if(mode == -1){
|
if(mode == -1){
|
||||||
//erase block
|
//erase block
|
||||||
Vars.world.removeBlock(tile);
|
tile.remove();
|
||||||
}else if(mode == 0){
|
}else if(mode == 0){
|
||||||
//erase ore
|
//erase ore
|
||||||
tile.clearOverlay();
|
tile.clearOverlay();
|
||||||
@@ -141,7 +140,7 @@ public enum EditorTool{
|
|||||||
if(tile.link().synthetic()){
|
if(tile.link().synthetic()){
|
||||||
Team dest = tile.getTeam();
|
Team dest = tile.getTeam();
|
||||||
if(dest == editor.drawTeam) return;
|
if(dest == editor.drawTeam) return;
|
||||||
fill(editor, x, y, false, t -> t.getTeamID() == dest.ordinal() && t.link().synthetic(), t -> t.setTeam(editor.drawTeam));
|
fill(editor, x, y, false, t -> t.getTeamID() == (int)dest.id && t.link().synthetic(), t -> t.setTeam(editor.drawTeam));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,6 @@ import arc.util.Structs;
|
|||||||
import mindustry.content.Blocks;
|
import mindustry.content.Blocks;
|
||||||
import mindustry.game.Team;
|
import mindustry.game.Team;
|
||||||
import mindustry.gen.TileOp;
|
import mindustry.gen.TileOp;
|
||||||
import mindustry.io.LegacyMapIO;
|
|
||||||
import mindustry.io.MapIO;
|
import mindustry.io.MapIO;
|
||||||
import mindustry.maps.Map;
|
import mindustry.maps.Map;
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
@@ -65,7 +64,7 @@ public class MapEditor{
|
|||||||
reset();
|
reset();
|
||||||
|
|
||||||
createTiles(pixmap.getWidth(), pixmap.getHeight());
|
createTiles(pixmap.getWidth(), pixmap.getHeight());
|
||||||
load(() -> LegacyMapIO.readPixmap(pixmap, tiles()));
|
load(() -> MapIO.readPixmap(pixmap, tiles()));
|
||||||
renderer.resize(width(), height());
|
renderer.resize(width(), height());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +85,7 @@ public class MapEditor{
|
|||||||
for(int x = 0; x < width(); x++){
|
for(int x = 0; x < width(); x++){
|
||||||
for(int y = 0; y < height(); y++){
|
for(int y = 0; y < height(); y++){
|
||||||
if(tiles[x][y].block().isMultiblock()){
|
if(tiles[x][y].block().isMultiblock()){
|
||||||
world.setBlock(tiles[x][y], tiles[x][y].block(), tiles[x][y].getTeam());
|
tiles[x][y].set(tiles[x][y].block(), tiles[x][y].getTeam());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -176,7 +175,7 @@ public class MapEditor{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
world.setBlock(tile(x, y), drawBlock, drawTeam);
|
tile(x, y).set(drawBlock, drawTeam);
|
||||||
}else{
|
}else{
|
||||||
boolean isFloor = drawBlock.isFloor() && drawBlock != Blocks.air;
|
boolean isFloor = drawBlock.isFloor() && drawBlock != Blocks.air;
|
||||||
|
|
||||||
@@ -185,7 +184,7 @@ public class MapEditor{
|
|||||||
|
|
||||||
//remove linked tiles blocking the way
|
//remove linked tiles blocking the way
|
||||||
if(!isFloor && (tile.isLinked() || tile.block().isMultiblock())){
|
if(!isFloor && (tile.isLinked() || tile.block().isMultiblock())){
|
||||||
world.removeBlock(tile.link());
|
tile.link().remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(isFloor){
|
if(isFloor){
|
||||||
|
|||||||
@@ -551,7 +551,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
|||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
for(Team team : Team.all){
|
for(Team team : Team.base()){
|
||||||
ImageButton button = new ImageButton(Tex.whiteui, Styles.clearTogglePartiali);
|
ImageButton button = new ImageButton(Tex.whiteui, Styles.clearTogglePartiali);
|
||||||
button.margin(4f);
|
button.margin(4f);
|
||||||
button.getImageCell().grow();
|
button.getImageCell().grow();
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ public class MapGenerateDialog extends FloatingDialog{
|
|||||||
tile.rotation(write.rotation);
|
tile.rotation(write.rotation);
|
||||||
tile.setFloor((Floor)content.block(write.floor));
|
tile.setFloor((Floor)content.block(write.floor));
|
||||||
tile.setBlock(content.block(write.block));
|
tile.setBlock(content.block(write.block));
|
||||||
tile.setTeam(Team.all[write.team]);
|
tile.setTeam(Team.get(write.team));
|
||||||
tile.setOverlay(content.block(write.ore));
|
tile.setOverlay(content.block(write.ore));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -367,7 +367,7 @@ public class MapGenerateDialog extends FloatingDialog{
|
|||||||
GenTile tile = buffer1[px][py];
|
GenTile tile = buffer1[px][py];
|
||||||
input.apply(x, y, content.block(tile.floor), content.block(tile.block), content.block(tile.ore));
|
input.apply(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.get(tile.team), tile.rotation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(int px = 0; px < pixmap.getWidth(); px++){
|
for(int px = 0; px < pixmap.getWidth(); px++){
|
||||||
@@ -415,7 +415,7 @@ public class MapGenerateDialog extends FloatingDialog{
|
|||||||
this.floor = floor.id;
|
this.floor = floor.id;
|
||||||
this.block = wall.id;
|
this.block = wall.id;
|
||||||
this.ore = ore.id;
|
this.ore = ore.id;
|
||||||
this.team = (byte)team.ordinal();
|
this.team = (byte) team.id;
|
||||||
this.rotation = (byte)rotation;
|
this.rotation = (byte)rotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -437,7 +437,7 @@ public class MapGenerateDialog extends FloatingDialog{
|
|||||||
ctile.setBlock(content.block(block));
|
ctile.setBlock(content.block(block));
|
||||||
ctile.setOverlay(content.block(ore));
|
ctile.setOverlay(content.block(ore));
|
||||||
ctile.rotation(rotation);
|
ctile.rotation(rotation);
|
||||||
ctile.setTeam(Team.all[team]);
|
ctile.setTeam(Team.get(team));
|
||||||
return ctile;
|
return ctile;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ public class MapView extends Element implements GestureListener{
|
|||||||
private boolean grid = false;
|
private boolean grid = false;
|
||||||
private GridImage image = new GridImage(0, 0);
|
private GridImage image = new GridImage(0, 0);
|
||||||
private Vec2 vec = new Vec2();
|
private Vec2 vec = new Vec2();
|
||||||
private Rectangle rect = new Rectangle();
|
private Rect rect = new Rect();
|
||||||
private Vec2[][] brushPolygons = new Vec2[MapEditor.brushSizes.length][0];
|
private Vec2[][] brushPolygons = new Vec2[MapEditor.brushSizes.length][0];
|
||||||
|
|
||||||
private boolean drawing;
|
private boolean drawing;
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ import static mindustry.Vars.*;
|
|||||||
|
|
||||||
/** Utility class for damaging in an area. */
|
/** Utility class for damaging in an area. */
|
||||||
public class Damage{
|
public class Damage{
|
||||||
private static Rectangle rect = new Rectangle();
|
private static Rect rect = new Rect();
|
||||||
private static Rectangle hitrect = new Rectangle();
|
private static Rect hitrect = new Rect();
|
||||||
private static Vec2 tr = new Vec2();
|
private static Vec2 tr = new Vec2();
|
||||||
private static GridBits bits = new GridBits(30, 30);
|
private static GridBits bits = new GridBits(30, 30);
|
||||||
private static IntQueue propagation = new IntQueue();
|
private static IntQueue propagation = new IntQueue();
|
||||||
@@ -88,7 +88,7 @@ public class Damage{
|
|||||||
tr.trns(angle, length);
|
tr.trns(angle, length);
|
||||||
Intc2 collider = (cx, cy) -> {
|
Intc2 collider = (cx, cy) -> {
|
||||||
Tile tile = world.ltile(cx, cy);
|
Tile tile = world.ltile(cx, cy);
|
||||||
if(tile != null && !collidedBlocks.contains(tile.pos()) && tile.entity != null && tile.getTeamID() != team.ordinal() && tile.entity.collide(hitter)){
|
if(tile != null && !collidedBlocks.contains(tile.pos()) && tile.entity != null && tile.getTeamID() != team.id && tile.entity.collide(hitter)){
|
||||||
tile.entity.collision(hitter);
|
tile.entity.collision(hitter);
|
||||||
collidedBlocks.add(tile.pos());
|
collidedBlocks.add(tile.pos());
|
||||||
hitter.getBulletType().hit(hitter, tile.worldx(), tile.worldy());
|
hitter.getBulletType().hit(hitter, tile.worldx(), tile.worldy());
|
||||||
@@ -127,7 +127,7 @@ public class Damage{
|
|||||||
|
|
||||||
Cons<Unit> cons = e -> {
|
Cons<Unit> cons = e -> {
|
||||||
e.hitbox(hitrect);
|
e.hitbox(hitrect);
|
||||||
Rectangle other = hitrect;
|
Rect other = hitrect;
|
||||||
other.y -= expand;
|
other.y -= expand;
|
||||||
other.x -= expand;
|
other.x -= expand;
|
||||||
other.width += expand * 2;
|
other.width += expand * 2;
|
||||||
@@ -259,7 +259,7 @@ public class Damage{
|
|||||||
for(int dx = -trad; dx <= trad; dx++){
|
for(int dx = -trad; dx <= trad; dx++){
|
||||||
for(int dy = -trad; dy <= trad; dy++){
|
for(int dy = -trad; dy <= trad; dy++){
|
||||||
Tile tile = world.tile(Math.round(x / tilesize) + dx, Math.round(y / tilesize) + dy);
|
Tile tile = world.tile(Math.round(x / tilesize) + dx, Math.round(y / tilesize) + dy);
|
||||||
if(tile != null && tile.entity != null && (team == null || state.teams.areEnemies(team, tile.getTeam())) && Mathf.dst(dx, dy) <= trad){
|
if(tile != null && tile.entity != null && (team == null ||team.isEnemy(tile.getTeam())) && Mathf.dst(dx, dy) <= trad){
|
||||||
tile.entity.damage(damage);
|
tile.entity.damage(damage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,11 +17,11 @@ public class EntityCollisions{
|
|||||||
private static final float seg = 1f;
|
private static final float seg = 1f;
|
||||||
|
|
||||||
//tile collisions
|
//tile collisions
|
||||||
private Rectangle tmp = new Rectangle();
|
private Rect tmp = new Rect();
|
||||||
private Vec2 vector = new Vec2();
|
private Vec2 vector = new Vec2();
|
||||||
private Vec2 l1 = new Vec2();
|
private Vec2 l1 = new Vec2();
|
||||||
private Rectangle r1 = new Rectangle();
|
private Rect r1 = new Rect();
|
||||||
private Rectangle r2 = new Rectangle();
|
private Rect r2 = new Rect();
|
||||||
|
|
||||||
//entity collisions
|
//entity collisions
|
||||||
private Array<SolidTrait> arrOut = new Array<>();
|
private Array<SolidTrait> arrOut = new Array<>();
|
||||||
@@ -57,7 +57,7 @@ public class EntityCollisions{
|
|||||||
|
|
||||||
public void moveDelta(SolidTrait entity, float deltax, float deltay, boolean x){
|
public void moveDelta(SolidTrait entity, float deltax, float deltay, boolean x){
|
||||||
|
|
||||||
Rectangle rect = r1;
|
Rect rect = r1;
|
||||||
entity.hitboxTile(rect);
|
entity.hitboxTile(rect);
|
||||||
entity.hitboxTile(r2);
|
entity.hitboxTile(r2);
|
||||||
rect.x += deltax;
|
rect.x += deltax;
|
||||||
@@ -84,7 +84,7 @@ public class EntityCollisions{
|
|||||||
entity.setY(entity.getY() + rect.y - r2.y);
|
entity.setY(entity.getY() + rect.y - r2.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean overlapsTile(Rectangle rect){
|
public boolean overlapsTile(Rect rect){
|
||||||
rect.getCenter(vector);
|
rect.getCenter(vector);
|
||||||
int r = 1;
|
int r = 1;
|
||||||
|
|
||||||
|
|||||||
@@ -19,13 +19,13 @@ public class EntityGroup<T extends Entity>{
|
|||||||
private final Array<T> entitiesToRemove = 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> entitiesToAdd = new Array<>(false, 32);
|
||||||
private final Array<T> intersectArray = new Array<>();
|
private final Array<T> intersectArray = new Array<>();
|
||||||
private final Rectangle intersectRect = new Rectangle();
|
private final Rect intersectRect = new Rect();
|
||||||
private IntMap<T> map;
|
private IntMap<T> map;
|
||||||
private QuadTree tree;
|
private QuadTree tree;
|
||||||
private Cons<T> removeListener;
|
private Cons<T> removeListener;
|
||||||
private Cons<T> addListener;
|
private Cons<T> addListener;
|
||||||
|
|
||||||
private final Rectangle viewport = new Rectangle();
|
private final Rect viewport = new Rect();
|
||||||
private int count = 0;
|
private int count = 0;
|
||||||
|
|
||||||
public EntityGroup(int id, Class<T> type, boolean useTree){
|
public EntityGroup(int id, Class<T> type, boolean useTree){
|
||||||
@@ -34,7 +34,7 @@ public class EntityGroup<T extends Entity>{
|
|||||||
this.type = type;
|
this.type = type;
|
||||||
|
|
||||||
if(useTree){
|
if(useTree){
|
||||||
tree = new QuadTree<>(new Rectangle(0, 0, 0, 0));
|
tree = new QuadTree<>(new Rect(0, 0, 0, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,7 +180,7 @@ public class EntityGroup<T extends Entity>{
|
|||||||
/** Resizes the internal quadtree, if it is enabled.*/
|
/** Resizes the internal quadtree, if it is enabled.*/
|
||||||
public void resize(float x, float y, float w, float h){
|
public void resize(float x, float y, float w, float h){
|
||||||
if(useTree){
|
if(useTree){
|
||||||
tree = new QuadTree<>(new Rectangle(x, y, w, h));
|
tree = new QuadTree<>(new Rect(x, y, w, h));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,18 @@
|
|||||||
package mindustry.entities;
|
package mindustry.entities;
|
||||||
|
|
||||||
import arc.struct.EnumSet;
|
import arc.func.*;
|
||||||
import arc.func.Cons;
|
import arc.math.*;
|
||||||
import arc.func.Boolf;
|
import arc.math.geom.*;
|
||||||
import arc.math.Mathf;
|
import mindustry.entities.traits.*;
|
||||||
import arc.math.geom.Geometry;
|
|
||||||
import arc.math.geom.Rectangle;
|
|
||||||
import mindustry.entities.traits.TargetTrait;
|
|
||||||
import mindustry.entities.type.*;
|
import mindustry.entities.type.*;
|
||||||
import mindustry.game.Team;
|
import mindustry.game.*;
|
||||||
import mindustry.world.Tile;
|
import mindustry.world.*;
|
||||||
|
|
||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
/** Utility class for unit and team interactions.*/
|
/** Utility class for unit and team interactions.*/
|
||||||
public class Units{
|
public class Units{
|
||||||
private static Rectangle hitrect = new Rectangle();
|
private static Rect hitrect = new Rect();
|
||||||
private static Unit result;
|
private static Unit result;
|
||||||
private static float cdist;
|
private static float cdist;
|
||||||
private static boolean boolResult;
|
private static boolean boolResult;
|
||||||
@@ -86,7 +83,7 @@ public class Units{
|
|||||||
public static TileEntity findEnemyTile(Team team, float x, float y, float range, Boolf<Tile> pred){
|
public static TileEntity findEnemyTile(Team team, float x, float y, float range, Boolf<Tile> pred){
|
||||||
if(team == Team.derelict) return null;
|
if(team == Team.derelict) return null;
|
||||||
|
|
||||||
for(Team enemy : state.teams.enemiesOf(team)){
|
for(Team enemy : team.enemies()){
|
||||||
TileEntity entity = indexer.findTile(enemy, x, y, range, pred, true);
|
TileEntity entity = indexer.findTile(enemy, x, y, range, pred, true);
|
||||||
if(entity != null){
|
if(entity != null){
|
||||||
return entity;
|
return entity;
|
||||||
@@ -157,7 +154,11 @@ public class Units{
|
|||||||
|
|
||||||
/** Iterates over all units in a rectangle. */
|
/** Iterates over all units in a rectangle. */
|
||||||
public static void nearby(Team team, float x, float y, float width, float height, Cons<Unit> cons){
|
public static void nearby(Team team, float x, float y, float width, float height, Cons<Unit> cons){
|
||||||
unitGroups[team.ordinal()].intersect(x, y, width, height, cons);
|
unitGroup.intersect(x, y, width, height, u -> {
|
||||||
|
if(u.getTeam() == team){
|
||||||
|
cons.get(u);
|
||||||
|
}
|
||||||
|
});
|
||||||
playerGroup.intersect(x, y, width, height, player -> {
|
playerGroup.intersect(x, y, width, height, player -> {
|
||||||
if(player.getTeam() == team){
|
if(player.getTeam() == team){
|
||||||
cons.get(player);
|
cons.get(player);
|
||||||
@@ -167,8 +168,8 @@ public class Units{
|
|||||||
|
|
||||||
/** Iterates over all units in a circle around this position. */
|
/** Iterates over all units in a circle around this position. */
|
||||||
public static void nearby(Team team, float x, float y, float radius, Cons<Unit> cons){
|
public static void nearby(Team team, float x, float y, float radius, Cons<Unit> cons){
|
||||||
unitGroups[team.ordinal()].intersect(x - radius, y - radius, radius*2f, radius*2f, unit -> {
|
unitGroup.intersect(x - radius, y - radius, radius*2f, radius*2f, unit -> {
|
||||||
if(unit.withinDst(x, y, radius)){
|
if(unit.getTeam() == team && unit.withinDst(x, y, radius)){
|
||||||
cons.get(unit);
|
cons.get(unit);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -182,45 +183,43 @@ public class Units{
|
|||||||
|
|
||||||
/** Iterates over all units in a rectangle. */
|
/** Iterates over all units in a rectangle. */
|
||||||
public static void nearby(float x, float y, float width, float height, Cons<Unit> cons){
|
public static void nearby(float x, float y, float width, float height, Cons<Unit> cons){
|
||||||
for(Team team : Team.all){
|
unitGroup.intersect(x, y, width, height, cons);
|
||||||
unitGroups[team.ordinal()].intersect(x, y, width, height, cons);
|
|
||||||
}
|
|
||||||
|
|
||||||
playerGroup.intersect(x, y, width, height, cons);
|
playerGroup.intersect(x, y, width, height, cons);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Iterates over all units in a rectangle. */
|
/** Iterates over all units in a rectangle. */
|
||||||
public static void nearby(Rectangle rect, Cons<Unit> cons){
|
public static void nearby(Rect rect, Cons<Unit> cons){
|
||||||
nearby(rect.x, rect.y, rect.width, rect.height, cons);
|
nearby(rect.x, rect.y, rect.width, rect.height, cons);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Iterates over all units that are enemies of this team. */
|
/** Iterates over all units that are enemies of this team. */
|
||||||
public static void nearbyEnemies(Team team, float x, float y, float width, float height, Cons<Unit> cons){
|
public static void nearbyEnemies(Team team, float x, float y, float width, float height, Cons<Unit> cons){
|
||||||
EnumSet<Team> targets = state.teams.enemiesOf(team);
|
unitGroup.intersect(x, y, width, height, u -> {
|
||||||
|
if(team.isEnemy(u.getTeam())){
|
||||||
for(Team other : targets){
|
cons.get(u);
|
||||||
unitGroups[other.ordinal()].intersect(x, y, width, height, cons);
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
playerGroup.intersect(x, y, width, height, player -> {
|
playerGroup.intersect(x, y, width, height, player -> {
|
||||||
if(targets.contains(player.getTeam())){
|
if(team.isEnemy(player.getTeam())){
|
||||||
cons.get(player);
|
cons.get(player);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Iterates over all units that are enemies of this team. */
|
/** Iterates over all units that are enemies of this team. */
|
||||||
public static void nearbyEnemies(Team team, Rectangle rect, Cons<Unit> cons){
|
public static void nearbyEnemies(Team team, Rect rect, Cons<Unit> cons){
|
||||||
nearbyEnemies(team, rect.x, rect.y, rect.width, rect.height, cons);
|
nearbyEnemies(team, rect.x, rect.y, rect.width, rect.height, cons);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Iterates over all units. */
|
/** Iterates over all units. */
|
||||||
public static void all(Cons<Unit> cons){
|
public static void all(Cons<Unit> cons){
|
||||||
for(Team team : Team.all){
|
unitGroup.all().each(cons);
|
||||||
unitGroups[team.ordinal()].all().each(cons);
|
|
||||||
}
|
|
||||||
|
|
||||||
playerGroup.all().each(cons);
|
playerGroup.all().each(cons);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void each(Team team, Cons<BaseUnit> cons){
|
||||||
|
unitGroup.all().each(t -> t.getTeam() == team, cons);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ public class ArtilleryBulletType extends BasicBulletType{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(mindustry.entities.type.Bullet b){
|
public void update(Bullet b){
|
||||||
super.update(b);
|
super.update(b);
|
||||||
|
|
||||||
if(b.timer.get(0, 3 + b.fslope() * 2f)){
|
if(b.timer.get(0, 3 + b.fslope() * 2f)){
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
package mindustry.entities.bullet;
|
package mindustry.entities.bullet;
|
||||||
|
|
||||||
import arc.math.geom.Rectangle;
|
import arc.math.geom.Rect;
|
||||||
import arc.util.Time;
|
import arc.util.Time;
|
||||||
import mindustry.content.Fx;
|
import mindustry.content.Fx;
|
||||||
import mindustry.entities.Units;
|
import mindustry.entities.Units;
|
||||||
import mindustry.entities.type.Bullet;
|
import mindustry.entities.type.Bullet;
|
||||||
|
|
||||||
public class FlakBulletType extends BasicBulletType{
|
public class FlakBulletType extends BasicBulletType{
|
||||||
protected static Rectangle rect = new Rectangle();
|
protected static Rect rect = new Rect();
|
||||||
protected float explodeRange = 30f;
|
protected float explodeRange = 30f;
|
||||||
|
|
||||||
public FlakBulletType(float speed, float damage){
|
public FlakBulletType(float speed, float damage){
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ public class Lightning extends TimedEntity implements DrawTrait, TimeTrait{
|
|||||||
public static final float lifetime = 10f;
|
public static final float lifetime = 10f;
|
||||||
|
|
||||||
private static final RandomXS128 random = new RandomXS128();
|
private static final RandomXS128 random = new RandomXS128();
|
||||||
private static final Rectangle rect = new Rectangle();
|
private static final Rect rect = new Rect();
|
||||||
private static final Array<Unit> entities = new Array<>();
|
private static final Array<Unit> entities = new Array<>();
|
||||||
private static final IntSet hit = new IntSet();
|
private static final IntSet hit = new IntSet();
|
||||||
private static final int maxChain = 8;
|
private static final int maxChain = 8;
|
||||||
|
|||||||
@@ -27,8 +27,8 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai
|
|||||||
private static final float maxLiquid = 70f;
|
private static final float maxLiquid = 70f;
|
||||||
private static final int maxGeneration = 2;
|
private static final int maxGeneration = 2;
|
||||||
private static final Color tmp = new Color();
|
private static final Color tmp = new Color();
|
||||||
private static final Rectangle rect = new Rectangle();
|
private static final Rect rect = new Rect();
|
||||||
private static final Rectangle rect2 = new Rectangle();
|
private static final Rect rect2 = new Rect();
|
||||||
private static int seeds;
|
private static int seeds;
|
||||||
|
|
||||||
private int loadedPosition = -1;
|
private int loadedPosition = -1;
|
||||||
@@ -151,13 +151,13 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void hitbox(Rectangle rectangle){
|
public void hitbox(Rect rect){
|
||||||
rectangle.setCenter(x, y).setSize(tilesize);
|
rect.setCenter(x, y).setSize(tilesize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void hitboxTile(Rectangle rectangle){
|
public void hitboxTile(Rect rect){
|
||||||
rectangle.setCenter(x, y).setSize(0f);
|
rect.setCenter(x, y).setSize(0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -343,7 +343,7 @@ public interface BuilderTrait extends Entity, TeamTrait{
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Rectangle bounds(Rectangle rect){
|
public Rect bounds(Rect rect){
|
||||||
if(breaking){
|
if(breaking){
|
||||||
return rect.set(-100f, -100f, 0f, 0f);
|
return rect.set(-100f, -100f, 0f, 0f);
|
||||||
}else{
|
}else{
|
||||||
|
|||||||
@@ -7,9 +7,9 @@ import mindustry.Vars;
|
|||||||
|
|
||||||
public interface SolidTrait extends QuadTreeObject, MoveTrait, VelocityTrait, Entity, Position{
|
public interface SolidTrait extends QuadTreeObject, MoveTrait, VelocityTrait, Entity, Position{
|
||||||
|
|
||||||
void hitbox(Rectangle rectangle);
|
void hitbox(Rect rect);
|
||||||
|
|
||||||
void hitboxTile(Rectangle rectangle);
|
void hitboxTile(Rect rect);
|
||||||
|
|
||||||
Vec2 lastPosition();
|
Vec2 lastPosition();
|
||||||
|
|
||||||
|
|||||||
@@ -126,6 +126,11 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
|||||||
this.team = team;
|
this.team = team;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return whether this unit counts toward the enemy amount in the wave UI. */
|
||||||
|
public boolean countsAsEnemy(){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public UnitType getType(){
|
public UnitType getType(){
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
@@ -180,23 +185,16 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Tile getClosest(BlockFlag flag){
|
public @Nullable Tile getClosest(BlockFlag flag){
|
||||||
return Geometry.findClosest(x, y, indexer.getAllied(team, flag));
|
return Geometry.findClosest(x, y, indexer.getAllied(team, flag));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Tile getClosestSpawner(){
|
public @Nullable Tile getClosestSpawner(){
|
||||||
return Geometry.findClosest(x, y, Vars.spawner.getGroundSpawns());
|
return Geometry.findClosest(x, y, Vars.spawner.getGroundSpawns());
|
||||||
}
|
}
|
||||||
|
|
||||||
public TileEntity getClosestEnemyCore(){
|
public @Nullable TileEntity getClosestEnemyCore(){
|
||||||
for(Team enemy : Vars.state.teams.enemiesOf(team)){
|
return Vars.state.teams.closestEnemyCore(x, y, team);
|
||||||
Tile tile = Geometry.findClosest(x, y, Vars.state.teams.get(enemy).cores);
|
|
||||||
if(tile != null){
|
|
||||||
return tile.entity;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public UnitState getStartState(){
|
public UnitState getStartState(){
|
||||||
@@ -354,18 +352,18 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void hitbox(Rectangle rectangle){
|
public void hitbox(Rect rect){
|
||||||
rectangle.setSize(type.hitsize).setCenter(x, y);
|
rect.setSize(type.hitsize).setCenter(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void hitboxTile(Rectangle rectangle){
|
public void hitboxTile(Rect rect){
|
||||||
rectangle.setSize(type.hitsizeTile).setCenter(x, y);
|
rect.setSize(type.hitsizeTile).setCenter(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityGroup targetGroup(){
|
public EntityGroup targetGroup(){
|
||||||
return unitGroups[team.ordinal()];
|
return unitGroup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -246,13 +246,13 @@ public class Bullet extends SolidEntity implements DamageTrait, ScaleTrait, Pool
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void hitbox(Rectangle rectangle){
|
public void hitbox(Rect rect){
|
||||||
rectangle.setSize(type.hitSize).setCenter(x, y);
|
rect.setSize(type.hitSize).setCenter(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void hitboxTile(Rectangle rectangle){
|
public void hitboxTile(Rect rect){
|
||||||
rectangle.setSize(type.hitSize).setCenter(x, y);
|
rect.setSize(type.hitSize).setCenter(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
|||||||
private static final int timerShootRight = 1;
|
private static final int timerShootRight = 1;
|
||||||
private static final float liftoffBoost = 0.2f;
|
private static final float liftoffBoost = 0.2f;
|
||||||
|
|
||||||
private static final Rectangle rect = new Rectangle();
|
private static final Rect rect = new Rect();
|
||||||
|
|
||||||
//region instance variables
|
//region instance variables
|
||||||
|
|
||||||
@@ -93,13 +93,13 @@ public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void hitbox(Rectangle rectangle){
|
public void hitbox(Rect rect){
|
||||||
rectangle.setSize(mech.hitsize).setCenter(x, y);
|
rect.setSize(mech.hitsize).setCenter(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void hitboxTile(Rectangle rectangle){
|
public void hitboxTile(Rect rect){
|
||||||
rectangle.setSize(mech.hitsize * 2f / 3f).setCenter(x, y);
|
rect.setSize(mech.hitsize * 2f / 3f).setCenter(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -124,7 +124,8 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{
|
|||||||
@CallSuper
|
@CallSuper
|
||||||
public void write(DataOutput stream) throws IOException{
|
public void write(DataOutput stream) throws IOException{
|
||||||
stream.writeShort((short)health);
|
stream.writeShort((short)health);
|
||||||
stream.writeByte(Pack.byteByte(tile.getTeamID(), tile.rotation())); //team + rotation
|
stream.writeByte(Pack.byteByte((byte)8, tile.rotation())); //rotation + marker to indicate that team is moved (8 isn't valid)
|
||||||
|
stream.writeByte(tile.getTeamID());
|
||||||
if(items != null) items.write(stream);
|
if(items != null) items.write(stream);
|
||||||
if(power != null) power.write(stream);
|
if(power != null) power.write(stream);
|
||||||
if(liquids != null) liquids.write(stream);
|
if(liquids != null) liquids.write(stream);
|
||||||
@@ -134,11 +135,11 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{
|
|||||||
@CallSuper
|
@CallSuper
|
||||||
public void read(DataInput stream, byte revision) throws IOException{
|
public void read(DataInput stream, byte revision) throws IOException{
|
||||||
health = stream.readUnsignedShort();
|
health = stream.readUnsignedShort();
|
||||||
byte tr = stream.readByte();
|
byte packedrot = stream.readByte();
|
||||||
byte team = Pack.leftByte(tr);
|
byte team = Pack.leftByte(packedrot) == 8 ? stream.readByte() : Pack.leftByte(packedrot);
|
||||||
byte rotation = Pack.rightByte(tr);
|
byte rotation = Pack.rightByte(packedrot);
|
||||||
|
|
||||||
tile.setTeam(Team.all[team]);
|
tile.setTeam(Team.get(team));
|
||||||
tile.rotation(rotation);
|
tile.rotation(rotation);
|
||||||
|
|
||||||
if(items != null) items.read(stream);
|
if(items != null) items.read(stream);
|
||||||
@@ -277,7 +278,7 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{
|
|||||||
Events.fire(new BlockDestroyEvent(tile));
|
Events.fire(new BlockDestroyEvent(tile));
|
||||||
block.breakSound.at(tile);
|
block.breakSound.at(tile);
|
||||||
block.onDestroyed(tile);
|
block.onDestroyed(tile);
|
||||||
world.removeBlock(tile);
|
tile.remove();
|
||||||
remove();
|
remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package mindustry.entities.type;
|
package mindustry.entities.type;
|
||||||
|
|
||||||
import arc.*;
|
import arc.*;
|
||||||
import arc.struct.*;
|
|
||||||
import arc.graphics.*;
|
import arc.graphics.*;
|
||||||
import arc.graphics.g2d.*;
|
import arc.graphics.g2d.*;
|
||||||
import arc.math.*;
|
import arc.math.*;
|
||||||
import arc.math.geom.*;
|
import arc.math.geom.*;
|
||||||
import arc.scene.ui.layout.*;
|
import arc.scene.ui.layout.*;
|
||||||
|
import arc.struct.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
import arc.util.ArcAnnotate.*;
|
import arc.util.ArcAnnotate.*;
|
||||||
import mindustry.content.*;
|
import mindustry.content.*;
|
||||||
@@ -16,13 +16,11 @@ import mindustry.entities.traits.*;
|
|||||||
import mindustry.entities.units.*;
|
import mindustry.entities.units.*;
|
||||||
import mindustry.game.EventType.*;
|
import mindustry.game.EventType.*;
|
||||||
import mindustry.game.*;
|
import mindustry.game.*;
|
||||||
import mindustry.game.Teams.*;
|
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.graphics.*;
|
import mindustry.graphics.*;
|
||||||
import mindustry.net.*;
|
import mindustry.net.*;
|
||||||
import mindustry.type.*;
|
import mindustry.type.*;
|
||||||
import mindustry.ui.*;
|
import mindustry.ui.*;
|
||||||
import mindustry.ui.Cicon;
|
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
import mindustry.world.blocks.*;
|
import mindustry.world.blocks.*;
|
||||||
|
|
||||||
@@ -90,7 +88,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
|||||||
if(isDead()) return false;
|
if(isDead()) return false;
|
||||||
|
|
||||||
if(other instanceof DamageTrait){
|
if(other instanceof DamageTrait){
|
||||||
return other instanceof TeamTrait && state.teams.areEnemies((((TeamTrait)other).getTeam()), team);
|
return other instanceof TeamTrait && (((TeamTrait)other).getTeam()).isEnemy(team);
|
||||||
}else{
|
}else{
|
||||||
return other instanceof Unit && ((Unit)other).isFlying() == isFlying();
|
return other instanceof Unit && ((Unit)other).isFlying() == isFlying();
|
||||||
}
|
}
|
||||||
@@ -158,7 +156,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
|||||||
this.item.amount = itemAmount;
|
this.item.amount = itemAmount;
|
||||||
this.item.item = content.item(itemID);
|
this.item.item = content.item(itemID);
|
||||||
this.dead = dead;
|
this.dead = dead;
|
||||||
this.team = Team.all[team];
|
this.team = Team.get(team);
|
||||||
this.health = health;
|
this.health = health;
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y;
|
||||||
@@ -169,7 +167,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
|||||||
public void writeSave(DataOutput stream, boolean net) throws IOException{
|
public void writeSave(DataOutput stream, boolean net) throws IOException{
|
||||||
if(item.item == null) item.item = Items.copper;
|
if(item.item == null) item.item = Items.copper;
|
||||||
|
|
||||||
stream.writeByte(team.ordinal());
|
stream.writeByte(team.id);
|
||||||
stream.writeBoolean(isDead());
|
stream.writeBoolean(isDead());
|
||||||
stream.writeFloat(net ? interpolator.target.x : x);
|
stream.writeFloat(net ? interpolator.target.x : x);
|
||||||
stream.writeFloat(net ? interpolator.target.y : y);
|
stream.writeFloat(net ? interpolator.target.y : y);
|
||||||
@@ -217,13 +215,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
|||||||
float fsize = getSize() / radScl;
|
float fsize = getSize() / radScl;
|
||||||
moveVector.setZero();
|
moveVector.setZero();
|
||||||
float cx = x - fsize/2f, cy = y - fsize/2f;
|
float cx = x - fsize/2f, cy = y - fsize/2f;
|
||||||
|
avoid(unitGroup.intersect(cx, cy, fsize, fsize));
|
||||||
for(Team team : Team.all){
|
|
||||||
if(team != getTeam() || !(this instanceof Player)){
|
|
||||||
avoid(unitGroups[team.ordinal()].intersect(cx, cy, fsize, fsize));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!(this instanceof Player)){
|
if(!(this instanceof Player)){
|
||||||
avoid(playerGroup.intersect(cx, cy, fsize, fsize));
|
avoid(playerGroup.intersect(cx, cy, fsize, fsize));
|
||||||
}
|
}
|
||||||
@@ -242,14 +234,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
|||||||
}
|
}
|
||||||
|
|
||||||
public @Nullable TileEntity getClosestCore(){
|
public @Nullable TileEntity getClosestCore(){
|
||||||
TeamData data = state.teams.get(team);
|
return state.teams.closestCore(x, y, team);
|
||||||
|
|
||||||
Tile tile = Geometry.findClosest(x, y, data.cores);
|
|
||||||
if(tile == null){
|
|
||||||
return null;
|
|
||||||
}else{
|
|
||||||
return tile.entity;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Floor getFloorOn(){
|
public Floor getFloorOn(){
|
||||||
@@ -275,7 +260,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
|||||||
}
|
}
|
||||||
|
|
||||||
//apply knockback based on spawns
|
//apply knockback based on spawns
|
||||||
if(getTeam() != waveTeam){
|
if(getTeam() != state.rules.waveTeam){
|
||||||
float relativeSize = state.rules.dropZoneRadius + getSize()/2f + 1f;
|
float relativeSize = state.rules.dropZoneRadius + getSize()/2f + 1f;
|
||||||
for(Tile spawn : spawner.getGroundSpawns()){
|
for(Tile spawn : spawner.getGroundSpawns()){
|
||||||
if(withinDst(spawn.worldx(), spawn.worldy(), relativeSize)){
|
if(withinDst(spawn.worldx(), spawn.worldy(), relativeSize)){
|
||||||
|
|||||||
@@ -32,6 +32,10 @@ public abstract class BaseDrone extends FlyingUnit{
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public boolean countsAsEnemy(){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCommand(UnitCommand command){
|
public void onCommand(UnitCommand command){
|
||||||
//do nothing, normal commands are not applicable here
|
//do nothing, normal commands are not applicable here
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
package mindustry.entities.type.base;
|
package mindustry.entities.type.base;
|
||||||
|
|
||||||
import arc.*;
|
import arc.*;
|
||||||
import arc.struct.*;
|
|
||||||
import arc.math.*;
|
import arc.math.*;
|
||||||
|
import arc.struct.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
import mindustry.*;
|
|
||||||
import mindustry.entities.*;
|
import mindustry.entities.*;
|
||||||
import mindustry.entities.traits.*;
|
import mindustry.entities.traits.*;
|
||||||
import mindustry.entities.type.*;
|
import mindustry.entities.type.*;
|
||||||
@@ -114,12 +113,10 @@ public class BuilderDrone extends BaseDrone implements BuilderTrait{
|
|||||||
public BuilderDrone(){
|
public BuilderDrone(){
|
||||||
if(reset.check()){
|
if(reset.check()){
|
||||||
Events.on(BuildSelectEvent.class, event -> {
|
Events.on(BuildSelectEvent.class, event -> {
|
||||||
EntityGroup<BaseUnit> group = unitGroups[event.team.ordinal()];
|
|
||||||
|
|
||||||
if(!(event.tile.entity instanceof BuildEntity)) return;
|
if(!(event.tile.entity instanceof BuildEntity)) return;
|
||||||
|
|
||||||
for(BaseUnit unit : group.all()){
|
for(BaseUnit unit : unitGroup.all()){
|
||||||
if(unit instanceof BuilderDrone){
|
if(unit instanceof BuilderDrone && unit.getTeam() == getTeam()){
|
||||||
BuilderDrone drone = (BuilderDrone)unit;
|
BuilderDrone drone = (BuilderDrone)unit;
|
||||||
if(drone.isBuilding()){
|
if(drone.isBuilding()){
|
||||||
//stop building if opposite building begins.
|
//stop building if opposite building begins.
|
||||||
@@ -189,7 +186,7 @@ public class BuilderDrone extends BaseDrone implements BuilderTrait{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(timer.get(timerTarget, 80) && Units.closestEnemy(getTeam(), x, y, 100f, u -> !(u instanceof BaseDrone)) == null && !isBuilding()){
|
if(timer.get(timerTarget, 80) && Units.closestEnemy(getTeam(), x, y, 100f, u -> !(u instanceof BaseDrone)) == null && !isBuilding()){
|
||||||
TeamData data = Vars.state.teams.get(team);
|
TeamData data = team.data();
|
||||||
if(!data.brokenBlocks.isEmpty()){
|
if(!data.brokenBlocks.isEmpty()){
|
||||||
BrokenBlock block = data.brokenBlocks.removeLast();
|
BrokenBlock block = data.brokenBlocks.removeLast();
|
||||||
if(Build.validPlace(getTeam(), block.x, block.y, content.block(block.block), block.rotation)){
|
if(Build.validPlace(getTeam(), block.x, block.y, content.block(block.block), block.rotation)){
|
||||||
|
|||||||
@@ -237,15 +237,15 @@ public class GroundUnit extends BaseUnit{
|
|||||||
|
|
||||||
protected void moveAwayFromCore(){
|
protected void moveAwayFromCore(){
|
||||||
Team enemy = null;
|
Team enemy = null;
|
||||||
for(Team team : Vars.state.teams.enemiesOf(team)){
|
for(Team team : team.enemies()){
|
||||||
if(Vars.state.teams.isActive(team)){
|
if(team.active()){
|
||||||
enemy = team;
|
enemy = team;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(enemy == null){
|
if(enemy == null){
|
||||||
for(Team team : Vars.state.teams.enemiesOf(team)){
|
for(Team team : team.enemies()){
|
||||||
enemy = team;
|
enemy = team;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,13 +7,14 @@ import mindustry.entities.type.BaseUnit;
|
|||||||
import mindustry.entities.type.TileEntity;
|
import mindustry.entities.type.TileEntity;
|
||||||
import mindustry.gen.Call;
|
import mindustry.gen.Call;
|
||||||
import mindustry.type.Item;
|
import mindustry.type.Item;
|
||||||
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
public class UnitDrops{
|
public class UnitDrops{
|
||||||
private static Item[] dropTable;
|
private static Item[] dropTable;
|
||||||
|
|
||||||
public static void dropItems(BaseUnit unit){
|
public static void dropItems(BaseUnit unit){
|
||||||
//items only dropped in waves for enemy team
|
//items only dropped in waves for enemy team
|
||||||
if(unit.getTeam() != Vars.waveTeam || !Vars.state.rules.unitDrops){
|
if(unit.getTeam() != state.rules.waveTeam || !Vars.state.rules.unitDrops){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -62,10 +62,13 @@ public class EventType{
|
|||||||
public static class PlayerChatEvent{
|
public static class PlayerChatEvent{
|
||||||
public final Player player;
|
public final Player player;
|
||||||
public final String message;
|
public final String message;
|
||||||
|
/** The original, unfiltered message. */
|
||||||
|
public final String originalMessage;
|
||||||
|
|
||||||
public PlayerChatEvent(Player player, String message){
|
public PlayerChatEvent(Player player, String message, String originalMessage){
|
||||||
this.player = player;
|
this.player = player;
|
||||||
this.message = message;
|
this.message = message;
|
||||||
|
this.originalMessage = originalMessage;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import arc.*;
|
|||||||
import arc.func.*;
|
import arc.func.*;
|
||||||
import mindustry.maps.*;
|
import mindustry.maps.*;
|
||||||
|
|
||||||
import static mindustry.Vars.waveTeam;
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
/** Defines preset rule sets. */
|
/** Defines preset rule sets. */
|
||||||
public enum Gamemode{
|
public enum Gamemode{
|
||||||
@@ -22,7 +22,7 @@ public enum Gamemode{
|
|||||||
attack(rules -> {
|
attack(rules -> {
|
||||||
rules.unitDrops = true;
|
rules.unitDrops = true;
|
||||||
rules.attackMode = true;
|
rules.attackMode = true;
|
||||||
}, map -> map.teams.contains(waveTeam.ordinal())),
|
}, map -> map.teams.contains((int)state.rules.waveTeam.id)),
|
||||||
pvp(rules -> {
|
pvp(rules -> {
|
||||||
rules.pvp = true;
|
rules.pvp = true;
|
||||||
rules.enemyCoreBuildRadius = 600f;
|
rules.enemyCoreBuildRadius = 600f;
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ public class MusicControl{
|
|||||||
|
|
||||||
/** Whether to play dark music.*/
|
/** Whether to play dark music.*/
|
||||||
private boolean isDark(){
|
private boolean isDark(){
|
||||||
if(!state.teams.get(player.getTeam()).cores.isEmpty() && state.teams.get(player.getTeam()).cores.first().entity.healthf() < 0.85f){
|
if(state.teams.get(player.getTeam()).hasCore() && state.teams.get(player.getTeam()).core().healthf() < 0.85f){
|
||||||
//core damaged -> dark
|
//core damaged -> dark
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -94,7 +94,7 @@ public class MusicControl{
|
|||||||
}
|
}
|
||||||
|
|
||||||
//dark based on enemies
|
//dark based on enemies
|
||||||
return Mathf.chance(state.enemies() / 70f + 0.1f);
|
return Mathf.chance(state.enemies / 70f + 0.1f);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Plays and fades in a music track. This must be called every frame.
|
/** Plays and fades in a music track. This must be called every frame.
|
||||||
|
|||||||
@@ -78,6 +78,12 @@ public class Rules{
|
|||||||
public boolean lighting = false;
|
public boolean lighting = false;
|
||||||
/** Ambient light color, used when lighting is enabled. */
|
/** Ambient light color, used when lighting is enabled. */
|
||||||
public Color ambientLight = new Color(0.01f, 0.01f, 0.04f, 0.99f);
|
public Color ambientLight = new Color(0.01f, 0.01f, 0.04f, 0.99f);
|
||||||
|
/** team of the player by default */
|
||||||
|
public Team defaultTeam = Team.sharded;
|
||||||
|
/** team of the enemy in waves/sectors */
|
||||||
|
public Team waveTeam = Team.crux;
|
||||||
|
/** special tags for additional info */
|
||||||
|
public StringMap tags = new StringMap();
|
||||||
|
|
||||||
/** Copies this ruleset exactly. Not very efficient at all, do not use often. */
|
/** Copies this ruleset exactly. Not very efficient at all, do not use often. */
|
||||||
public Rules copy(){
|
public Rules copy(){
|
||||||
|
|||||||
@@ -254,7 +254,7 @@ public class Schematics implements Loadable{
|
|||||||
Tile tile = world.tile(st.x + ox, st.y + oy);
|
Tile tile = world.tile(st.x + ox, st.y + oy);
|
||||||
if(tile == null) return;
|
if(tile == null) return;
|
||||||
|
|
||||||
world.setBlock(tile, st.block, defaultTeam);
|
tile.set(st.block, state.rules.defaultTeam);
|
||||||
tile.rotation(st.rotation);
|
tile.rotation(st.rotation);
|
||||||
if(st.block.posConfig){
|
if(st.block.posConfig){
|
||||||
tile.configureAny(Pos.get(tile.x - st.x + Pos.x(st.config), tile.y - st.y + Pos.y(st.config)));
|
tile.configureAny(Pos.get(tile.x - st.x + Pos.x(st.config), tile.y - st.y + Pos.y(st.config)));
|
||||||
|
|||||||
@@ -1,27 +1,102 @@
|
|||||||
package mindustry.game;
|
package mindustry.game;
|
||||||
|
|
||||||
import arc.Core;
|
import arc.*;
|
||||||
import arc.graphics.Color;
|
import arc.graphics.*;
|
||||||
|
import arc.math.*;
|
||||||
|
import arc.struct.*;
|
||||||
|
import arc.util.*;
|
||||||
|
import mindustry.game.Teams.*;
|
||||||
import mindustry.graphics.*;
|
import mindustry.graphics.*;
|
||||||
|
import mindustry.world.blocks.storage.CoreBlock.*;
|
||||||
|
|
||||||
public enum Team{
|
import static mindustry.Vars.*;
|
||||||
derelict(Color.valueOf("4d4e58")),
|
|
||||||
sharded(Pal.accent),
|
|
||||||
crux(Color.valueOf("e82d2d")),
|
|
||||||
green(Color.valueOf("4dd98b")),
|
|
||||||
purple(Color.valueOf("9a4bdf")),
|
|
||||||
blue(Color.royal.cpy());
|
|
||||||
|
|
||||||
public final static Team[] all = values();
|
public class Team implements Comparable<Team>{
|
||||||
|
public final byte id;
|
||||||
public final Color color;
|
public final Color color;
|
||||||
public final int intColor;
|
public String name;
|
||||||
|
|
||||||
Team(Color color){
|
/** All 256 registered teams. */
|
||||||
|
private static final Team[] all = new Team[256];
|
||||||
|
/** The 6 base teams used in the editor. */
|
||||||
|
private static final Team[] baseTeams = new Team[6];
|
||||||
|
|
||||||
|
public final static Team
|
||||||
|
derelict = new Team(0, "derelict", Color.valueOf("4d4e58")),
|
||||||
|
sharded = new Team(1, "sharded", Pal.accent.cpy()),
|
||||||
|
crux = new Team(2, "crux", Color.valueOf("e82d2d")),
|
||||||
|
green = new Team(3, "green", Color.valueOf("4dd98b")),
|
||||||
|
purple = new Team(4, "purple", Color.valueOf("9a4bdf")),
|
||||||
|
blue = new Team(5, "blue", Color.royal.cpy());
|
||||||
|
|
||||||
|
static{
|
||||||
|
Mathf.random.setSeed(7);
|
||||||
|
//create the whole 256 placeholder teams
|
||||||
|
for(int i = 6; i < all.length; i++){
|
||||||
|
new Team(i, "team#" + i, Color.HSVtoRGB(360f * Mathf.random(), 100f * Mathf.random(0.6f, 1f), 100f * Mathf.random(0.8f, 1f), 1f));
|
||||||
|
}
|
||||||
|
Mathf.random.setSeed(new RandomXS128().nextLong());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Team get(int id){
|
||||||
|
return all[Pack.u((byte)id)];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return the 6 base team colors. */
|
||||||
|
public static Team[] base(){
|
||||||
|
return baseTeams;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @return all the teams - do not use this for lookup! */
|
||||||
|
public static Team[] all(){
|
||||||
|
return all;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Team(int id, String name, Color color){
|
||||||
|
this.name = name;
|
||||||
this.color = color;
|
this.color = color;
|
||||||
intColor = Color.rgba8888(color);
|
this.id = (byte)id;
|
||||||
|
|
||||||
|
int us = Pack.u(this.id);
|
||||||
|
if(us < 6) baseTeams[us] = this;
|
||||||
|
all[us] = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Array<Team> enemies(){
|
||||||
|
return state.teams.enemiesOf(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TeamData data(){
|
||||||
|
return state.teams.get(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CoreEntity core(){
|
||||||
|
return data().core();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean active(){
|
||||||
|
return state.teams.isActive(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEnemy(Team other){
|
||||||
|
return state.teams.areEnemies(this, other);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Array<CoreEntity> cores(){
|
||||||
|
return state.teams.cores(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String localized(){
|
public String localized(){
|
||||||
return Core.bundle.get("team." + name() + ".name");
|
return Core.bundle.get("team." + name + ".name", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int compareTo(Team team){
|
||||||
|
return Integer.compare(id, team.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString(){
|
||||||
|
return name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,61 +1,168 @@
|
|||||||
package mindustry.game;
|
package mindustry.game;
|
||||||
|
|
||||||
|
import arc.func.*;
|
||||||
|
import arc.math.geom.*;
|
||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
import mindustry.*;
|
import arc.util.ArcAnnotate.*;
|
||||||
import mindustry.world.*;
|
import arc.util.*;
|
||||||
|
import mindustry.entities.type.*;
|
||||||
|
import mindustry.world.blocks.storage.CoreBlock.*;
|
||||||
|
|
||||||
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
/** Class for various team-based utilities. */
|
/** Class for various team-based utilities. */
|
||||||
public class Teams{
|
public class Teams{
|
||||||
private TeamData[] map = new TeamData[Team.all.length];
|
/** Maps team IDs to team data. */
|
||||||
|
private TeamData[] map = new TeamData[256];
|
||||||
|
/** Active teams. */
|
||||||
|
private Array<TeamData> active = new Array<>();
|
||||||
|
|
||||||
/**
|
public @Nullable CoreEntity closestEnemyCore(float x, float y, Team team){
|
||||||
* Register a team.
|
for(TeamData data : active){
|
||||||
* @param team The team type enum.
|
if(areEnemies(team, data.team)){
|
||||||
* @param enemies The array of enemies of this team. Any team not in this array is considered neutral.
|
CoreEntity tile = Geometry.findClosest(x, y, data.cores);
|
||||||
*/
|
if(tile != null){
|
||||||
public void add(Team team, Team... enemies){
|
return tile;
|
||||||
map[team.ordinal()] = new TeamData(team, EnumSet.of(enemies));
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public @Nullable CoreEntity closestCore(float x, float y, Team team){
|
||||||
|
return Geometry.findClosest(x, y, get(team).cores);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Array<Team> enemiesOf(Team team){
|
||||||
|
return get(team).enemies;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean eachEnemyCore(Team team, Boolf<CoreEntity> ret){
|
||||||
|
for(TeamData data : active){
|
||||||
|
if(areEnemies(team, data.team)){
|
||||||
|
for(CoreEntity tile : data.cores){
|
||||||
|
if(ret.get(tile)){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void eachEnemyCore(Team team, Cons<TileEntity> ret){
|
||||||
|
for(TeamData data : active){
|
||||||
|
if(areEnemies(team, data.team)){
|
||||||
|
for(TileEntity tile : data.cores){
|
||||||
|
ret.get(tile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns team data by type. */
|
/** Returns team data by type. */
|
||||||
public TeamData get(Team team){
|
public TeamData get(Team team){
|
||||||
if(map[team.ordinal()] == null){
|
if(map[Pack.u(team.id)] == null){
|
||||||
add(team, Array.with(Team.all).select(t -> t != team).toArray(Team.class));
|
map[Pack.u(team.id)] = new TeamData(team);
|
||||||
}
|
}
|
||||||
return map[team.ordinal()];
|
return map[Pack.u(team.id)];
|
||||||
|
}
|
||||||
|
|
||||||
|
public Array<CoreEntity> playerCores(){
|
||||||
|
return get(state.rules.defaultTeam).cores;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Do not modify! */
|
||||||
|
public Array<CoreEntity> cores(Team team){
|
||||||
|
return get(team).cores;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 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 team == Vars.waveTeam || get(team).cores.size > 0;
|
return team == state.rules.waveTeam || get(team).cores.size > 0;
|
||||||
}
|
|
||||||
|
|
||||||
/** Returns a set of all teams that are enemies of this team. */
|
|
||||||
public EnumSet<Team> enemiesOf(Team team){
|
|
||||||
return get(team).enemies;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Returns whether {@param other} is an enemy of {@param #team}. */
|
/** Returns whether {@param other} is an enemy of {@param #team}. */
|
||||||
public boolean areEnemies(Team team, Team other){
|
public boolean areEnemies(Team team, Team other){
|
||||||
return enemiesOf(team).contains(other);
|
//todo what about derelict?
|
||||||
|
return team != other;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Allocates a new array with the active teams.
|
public boolean canInteract(Team team, Team other){
|
||||||
* Never call in the main game loop.*/
|
return team == other || other == Team.derelict;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Do not modify. */
|
||||||
public Array<TeamData> getActive(){
|
public Array<TeamData> getActive(){
|
||||||
return Array.select(map, t -> t != null);
|
return active;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class TeamData{
|
public void registerCore(CoreEntity core){
|
||||||
public final ObjectSet<Tile> cores = new ObjectSet<>();
|
TeamData data = get(core.getTeam());
|
||||||
public final EnumSet<Team> enemies;
|
//add core if not present
|
||||||
|
if(!data.cores.contains(core)){
|
||||||
|
data.cores.add(core);
|
||||||
|
}
|
||||||
|
|
||||||
|
//register in active list if needed
|
||||||
|
if(data.active() && !active.contains(data)){
|
||||||
|
active.add(data);
|
||||||
|
updateEnemies();
|
||||||
|
indexer.updateTeamIndex(data.team);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unregisterCore(CoreEntity entity){
|
||||||
|
TeamData data = get(entity.getTeam());
|
||||||
|
//remove core
|
||||||
|
data.cores.remove(entity);
|
||||||
|
//unregister in active list
|
||||||
|
if(!data.active()){
|
||||||
|
active.remove(data);
|
||||||
|
updateEnemies();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateEnemies(){
|
||||||
|
if(!active.contains(get(state.rules.waveTeam))){
|
||||||
|
active.add(get(state.rules.waveTeam));
|
||||||
|
}
|
||||||
|
|
||||||
|
for(TeamData data : active){
|
||||||
|
data.enemies.clear();
|
||||||
|
for(TeamData other : active){
|
||||||
|
if(areEnemies(data.team, other.team)){
|
||||||
|
data.enemies.add(other.team);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TeamData{
|
||||||
|
public final Array<CoreEntity> cores = new Array<>();
|
||||||
|
public final Array<Team> enemies = new Array<>();
|
||||||
public final Team team;
|
public final Team team;
|
||||||
public Queue<BrokenBlock> brokenBlocks = new Queue<>();
|
public Queue<BrokenBlock> brokenBlocks = new Queue<>();
|
||||||
|
|
||||||
public TeamData(Team team, EnumSet<Team> enemies){
|
public TeamData(Team team){
|
||||||
this.team = team;
|
this.team = team;
|
||||||
this.enemies = enemies;
|
}
|
||||||
|
|
||||||
|
public boolean active(){
|
||||||
|
return team == state.rules.waveTeam || cores.size > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasCore(){
|
||||||
|
return cores.size > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean noCores(){
|
||||||
|
return cores.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CoreEntity core(){
|
||||||
|
return cores.first();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import arc.scene.ui.*;
|
|||||||
import arc.scene.ui.layout.*;
|
import arc.scene.ui.layout.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
import mindustry.content.*;
|
import mindustry.content.*;
|
||||||
|
import mindustry.entities.type.*;
|
||||||
import mindustry.game.EventType.*;
|
import mindustry.game.EventType.*;
|
||||||
import mindustry.graphics.*;
|
import mindustry.graphics.*;
|
||||||
import mindustry.type.*;
|
import mindustry.type.*;
|
||||||
@@ -161,11 +162,11 @@ public class Tutorial{
|
|||||||
},
|
},
|
||||||
withdraw(() -> event("withdraw")){
|
withdraw(() -> event("withdraw")){
|
||||||
void begin(){
|
void begin(){
|
||||||
state.teams.get(defaultTeam).cores.first().entity.items.add(Items.copper, 10);
|
state.teams.playerCores().first().items.add(Items.copper, 10);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
deposit(() -> event("deposit")),
|
deposit(() -> event("deposit")),
|
||||||
waves(() -> state.wave > 2 && state.enemies() <= 0 && !spawner.isSpawning()){
|
waves(() -> state.wave > 2 && state.enemies <= 0 && !spawner.isSpawning()){
|
||||||
void begin(){
|
void begin(){
|
||||||
state.rules.waveTimer = true;
|
state.rules.waveTimer = true;
|
||||||
logic.runWave();
|
logic.runWave();
|
||||||
@@ -239,18 +240,18 @@ public class Tutorial{
|
|||||||
//utility
|
//utility
|
||||||
|
|
||||||
static void placeBlocks(){
|
static void placeBlocks(){
|
||||||
Tile core = state.teams.get(defaultTeam).cores.first();
|
TileEntity core = state.teams.playerCores().first();
|
||||||
for(int i = 0; i < blocksToBreak; i++){
|
for(int i = 0; i < blocksToBreak; i++){
|
||||||
world.removeBlock(world.ltile(core.x + blockOffset, core.y + i));
|
world.ltile(core.tile.x + blockOffset, core.tile.y + i).remove();
|
||||||
world.tile(core.x + blockOffset, core.y + i).setBlock(Blocks.scrapWall, defaultTeam);
|
world.tile(core.tile.x + blockOffset, core.tile.y + i).setBlock(Blocks.scrapWall, state.rules.defaultTeam);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean blocksBroken(){
|
static boolean blocksBroken(){
|
||||||
Tile core = state.teams.get(defaultTeam).cores.first();
|
TileEntity core = state.teams.playerCores().first();
|
||||||
|
|
||||||
for(int i = 0; i < blocksToBreak; i++){
|
for(int i = 0; i < blocksToBreak; i++){
|
||||||
if(world.tile(core.x + blockOffset, core.y + i).block() == Blocks.scrapWall){
|
if(world.tile(core.tile.x + blockOffset, core.tile.y + i).block() == Blocks.scrapWall){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -270,7 +271,7 @@ public class Tutorial{
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int item(Item item){
|
static int item(Item item){
|
||||||
return state.teams.get(defaultTeam).cores.isEmpty() ? 0 : state.teams.get(defaultTeam).cores.first().entity.items.get(item);
|
return state.rules.defaultTeam.data().noCores() ? 0 : state.rules.defaultTeam.core().items.get(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean toggled(String name){
|
static boolean toggled(String name){
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ public class MinimapRenderer implements Disposable{
|
|||||||
private Pixmap pixmap;
|
private Pixmap pixmap;
|
||||||
private Texture texture;
|
private Texture texture;
|
||||||
private TextureRegion region;
|
private TextureRegion region;
|
||||||
private Rectangle rect = new Rectangle();
|
private Rect rect = new Rect();
|
||||||
private float zoom = 4;
|
private float zoom = 4;
|
||||||
|
|
||||||
public MinimapRenderer(){
|
public MinimapRenderer(){
|
||||||
|
|||||||
@@ -10,20 +10,19 @@ import mindustry.*;
|
|||||||
import mindustry.content.*;
|
import mindustry.content.*;
|
||||||
import mindustry.entities.*;
|
import mindustry.entities.*;
|
||||||
import mindustry.entities.type.*;
|
import mindustry.entities.type.*;
|
||||||
import mindustry.game.*;
|
|
||||||
import mindustry.input.*;
|
import mindustry.input.*;
|
||||||
import mindustry.type.Category;
|
import mindustry.type.*;
|
||||||
import mindustry.ui.Cicon;
|
import mindustry.ui.*;
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
import mindustry.world.blocks.units.MechPad;
|
import mindustry.world.blocks.units.*;
|
||||||
import mindustry.world.meta.BlockFlag;
|
import mindustry.world.meta.*;
|
||||||
|
|
||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
public class OverlayRenderer{
|
public class OverlayRenderer{
|
||||||
private static final float indicatorLength = 14f;
|
private static final float indicatorLength = 14f;
|
||||||
private static final float spawnerMargin = tilesize*11f;
|
private static final float spawnerMargin = tilesize*11f;
|
||||||
private static final Rectangle rect = new Rectangle();
|
private static final Rect rect = new Rect();
|
||||||
private float buildFadeTime;
|
private float buildFadeTime;
|
||||||
|
|
||||||
public void drawBottom(){
|
public void drawBottom(){
|
||||||
@@ -95,17 +94,15 @@ public class OverlayRenderer{
|
|||||||
Lines.stroke(buildFadeTime * 2f);
|
Lines.stroke(buildFadeTime * 2f);
|
||||||
|
|
||||||
if(buildFadeTime > 0.005f){
|
if(buildFadeTime > 0.005f){
|
||||||
for(Team enemy : state.teams.enemiesOf(player.getTeam())){
|
state.teams.eachEnemyCore(player.getTeam(), core -> {
|
||||||
for(Tile core : state.teams.get(enemy).cores){
|
float dst = core.dst(player);
|
||||||
float dst = Mathf.dst(player.x, player.y, core.drawx(), core.drawy());
|
if(dst < state.rules.enemyCoreBuildRadius * 1.5f){
|
||||||
if(dst < state.rules.enemyCoreBuildRadius * 1.5f){
|
Draw.color(Color.darkGray);
|
||||||
Draw.color(Color.darkGray);
|
Lines.circle(core.x, core.y - 2, state.rules.enemyCoreBuildRadius);
|
||||||
Lines.circle(core.drawx(), core.drawy() - 2, state.rules.enemyCoreBuildRadius);
|
Draw.color(Pal.accent, core.getTeam().color, 0.5f + Mathf.absin(Time.time(), 10f, 0.5f));
|
||||||
Draw.color(Pal.accent, enemy.color, 0.5f + Mathf.absin(Time.time(), 10f, 0.5f));
|
Lines.circle(core.x, core.y, state.rules.enemyCoreBuildRadius);
|
||||||
Lines.circle(core.drawx(), core.drawy(), state.rules.enemyCoreBuildRadius);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Lines.stroke(2f);
|
Lines.stroke(2f);
|
||||||
|
|||||||
@@ -300,7 +300,7 @@ public class DesktopInput extends InputHandler{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Core.input.keyTap(Binding.clear_building)){
|
if(Core.input.keyTap(Binding.clear_building) || isPlacing()){
|
||||||
lastSchematic = null;
|
lastSchematic = null;
|
||||||
selectRequests.clear();
|
selectRequests.clear();
|
||||||
}
|
}
|
||||||
@@ -397,7 +397,7 @@ public class DesktopInput extends InputHandler{
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(mode == placing && block != null){
|
if(mode == placing && block != null){
|
||||||
if(!overrideLineRotation && !Core.input.keyDown(Binding.diagonal_placement) && (selectX != cursorX || selectY != cursorY) && ((int) Core.input.axisTap(Binding.rotate) != 0)){
|
if(!overrideLineRotation && !Core.input.keyDown(Binding.diagonal_placement) && (selectX != cursorX || selectY != cursorY) && ((int)Core.input.axisTap(Binding.rotate) != 0)){
|
||||||
rotation = ((int)((Angles.angle(selectX, selectY, cursorX, cursorY) + 45) / 90f)) % 4;
|
rotation = ((int)((Angles.angle(selectX, selectY, cursorX, cursorY) + 45) / 90f)) % 4;
|
||||||
overrideLineRotation = true;
|
overrideLineRotation = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
|||||||
/** Maximum line length. */
|
/** Maximum line length. */
|
||||||
final static int maxLength = 100;
|
final static int maxLength = 100;
|
||||||
final static Vec2 stackTrns = new Vec2();
|
final static Vec2 stackTrns = new Vec2();
|
||||||
final static Rectangle r1 = new Rectangle(), r2 = new Rectangle();
|
final static Rect r1 = new Rect(), r2 = new Rect();
|
||||||
/** Distance on the back from where items originate. */
|
/** Distance on the back from where items originate. */
|
||||||
final static float backTrns = 3f;
|
final static float backTrns = 3f;
|
||||||
|
|
||||||
@@ -402,7 +402,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(BrokenBlock req : state.teams.get(player.getTeam()).brokenBlocks){
|
for(BrokenBlock req : player.getTeam().data().brokenBlocks){
|
||||||
Block block = content.block(req.block);
|
Block block = content.block(req.block);
|
||||||
if(block.bounds(req.x, req.y, Tmp.r2).overlaps(Tmp.r1)){
|
if(block.bounds(req.x, req.y, Tmp.r2).overlaps(Tmp.r1)){
|
||||||
drawSelected(req.x, req.y, content.block(req.block), Pal.remove);
|
drawSelected(req.x, req.y, content.block(req.block), Pal.remove);
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ public class MobileInput extends InputHandler implements GestureListener{
|
|||||||
}else{
|
}else{
|
||||||
Tile tile = world.ltileWorld(x, y);
|
Tile tile = world.ltileWorld(x, y);
|
||||||
|
|
||||||
if(tile != null && tile.synthetic() && state.teams.areEnemies(player.getTeam(), tile.getTeam())){
|
if(tile != null && tile.synthetic() && player.getTeam().isEnemy(tile.getTeam())){
|
||||||
TileEntity entity = tile.entity;
|
TileEntity entity = tile.entity;
|
||||||
player.setMineTile(null);
|
player.setMineTile(null);
|
||||||
player.target = entity;
|
player.target = entity;
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ public class JsonIO{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void writeValue(Object value, Class knownType, Class elementType){
|
public void writeValue(Object value, Class knownType, Class elementType){
|
||||||
if(value instanceof mindustry.ctype.MappableContent){
|
if(value instanceof MappableContent){
|
||||||
try{
|
try{
|
||||||
getWriter().value(((MappableContent)value).name);
|
getWriter().value(((MappableContent)value).name);
|
||||||
}catch(IOException e){
|
}catch(IOException e){
|
||||||
@@ -95,6 +95,18 @@ public class JsonIO{
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
json.setSerializer(Team.class, new Serializer<Team>(){
|
||||||
|
@Override
|
||||||
|
public void write(Json json, Team object, Class knownType){
|
||||||
|
json.writeValue(object.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Team read(Json json, JsonValue jsonData, Class type){
|
||||||
|
return Team.get(jsonData.asInt());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
json.setSerializer(Block.class, new Serializer<Block>(){
|
json.setSerializer(Block.class, new Serializer<Block>(){
|
||||||
@Override
|
@Override
|
||||||
public void write(Json json, Block object, Class knownType){
|
public void write(Json json, Block object, Class knownType){
|
||||||
|
|||||||
@@ -1,214 +0,0 @@
|
|||||||
package mindustry.io;
|
|
||||||
|
|
||||||
import arc.struct.*;
|
|
||||||
import arc.files.*;
|
|
||||||
import arc.graphics.*;
|
|
||||||
import arc.util.*;
|
|
||||||
import arc.util.serialization.*;
|
|
||||||
import mindustry.content.*;
|
|
||||||
import mindustry.ctype.ContentType;
|
|
||||||
import mindustry.game.*;
|
|
||||||
import mindustry.io.MapIO.*;
|
|
||||||
import mindustry.maps.*;
|
|
||||||
import mindustry.world.*;
|
|
||||||
import mindustry.world.LegacyColorMapper.*;
|
|
||||||
import mindustry.world.blocks.*;
|
|
||||||
|
|
||||||
import java.io.*;
|
|
||||||
import java.util.zip.*;
|
|
||||||
|
|
||||||
import static mindustry.Vars.*;
|
|
||||||
|
|
||||||
/** Map IO for the "old" .mmap format.
|
|
||||||
* Differentiate between legacy maps and new maps by checking the extension (or the header).*/
|
|
||||||
public class LegacyMapIO{
|
|
||||||
private static final ObjectMap<String, String> fallback = ObjectMap.of("alpha-dart-mech-pad", "dart-mech-pad");
|
|
||||||
private static final Json json = new Json();
|
|
||||||
|
|
||||||
/* Convert a map from the old format to the new format. */
|
|
||||||
public static void convertMap(Fi in, Fi out) throws IOException{
|
|
||||||
Map map = readMap(in, true);
|
|
||||||
|
|
||||||
String waves = map.tags.get("waves", "[]");
|
|
||||||
Array<SpawnGroup> groups = new Array<>(json.fromJson(SpawnGroup[].class, waves));
|
|
||||||
|
|
||||||
Tile[][] tiles = world.createTiles(map.width, map.height);
|
|
||||||
for(int x = 0; x < map.width; x++){
|
|
||||||
for(int y = 0; y < map.height; y++){
|
|
||||||
tiles[x][y] = new CachedTile();
|
|
||||||
tiles[x][y].x = (short)x;
|
|
||||||
tiles[x][y].y = (short)y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
state.rules.spawns = groups;
|
|
||||||
readTiles(map, tiles);
|
|
||||||
MapIO.writeMap(out, map);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Map readMap(Fi file, boolean custom) throws IOException{
|
|
||||||
try(DataInputStream stream = new DataInputStream(file.read(1024))){
|
|
||||||
StringMap tags = new StringMap();
|
|
||||||
|
|
||||||
//meta is uncompressed
|
|
||||||
int version = stream.readInt();
|
|
||||||
if(version != 1){
|
|
||||||
throw new IOException("Outdated legacy map format");
|
|
||||||
}
|
|
||||||
int build = stream.readInt();
|
|
||||||
short width = stream.readShort(), height = stream.readShort();
|
|
||||||
byte tagAmount = stream.readByte();
|
|
||||||
|
|
||||||
for(int i = 0; i < tagAmount; i++){
|
|
||||||
String name = stream.readUTF();
|
|
||||||
String value = stream.readUTF();
|
|
||||||
tags.put(name, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Map(file, width, height, tags, custom, version, build);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void readTiles(Map map, Tile[][] tiles) throws IOException{
|
|
||||||
readTiles(map, (x, y) -> tiles[x][y]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void readTiles(Map map, TileProvider tiles) throws IOException{
|
|
||||||
readTiles(map.file, map.width, map.height, tiles);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void readTiles(Fi file, int width, int height, Tile[][] tiles) throws IOException{
|
|
||||||
readTiles(file, width, height, (x, y) -> tiles[x][y]);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void readTiles(Fi file, int width, int height, TileProvider tiles) throws IOException{
|
|
||||||
try(BufferedInputStream input = file.read(bufferSize)){
|
|
||||||
|
|
||||||
//read map
|
|
||||||
{
|
|
||||||
DataInputStream stream = new DataInputStream(input);
|
|
||||||
|
|
||||||
stream.readInt(); //version
|
|
||||||
stream.readInt(); //build
|
|
||||||
stream.readInt(); //width + height
|
|
||||||
byte tagAmount = stream.readByte();
|
|
||||||
|
|
||||||
for(int i = 0; i < tagAmount; i++){
|
|
||||||
stream.readUTF(); //key
|
|
||||||
stream.readUTF(); //val
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try(DataInputStream stream = new DataInputStream(new InflaterInputStream(input))){
|
|
||||||
|
|
||||||
try{
|
|
||||||
byte mapped = stream.readByte();
|
|
||||||
IntMap<Block> idmap = new IntMap<>();
|
|
||||||
IntMap<String> namemap = new IntMap<>();
|
|
||||||
|
|
||||||
for(int i = 0; i < mapped; i++){
|
|
||||||
byte type = stream.readByte();
|
|
||||||
short total = stream.readShort();
|
|
||||||
|
|
||||||
for(int j = 0; j < total; j++){
|
|
||||||
String name = stream.readUTF();
|
|
||||||
if(type == 1){
|
|
||||||
Block res = content.getByName(ContentType.block, fallback.get(name, name));
|
|
||||||
idmap.put(j, res == null ? Blocks.air : res);
|
|
||||||
namemap.put(j, fallback.get(name, name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//read floor and create tiles first
|
|
||||||
for(int i = 0; i < width * height; i++){
|
|
||||||
int x = i % width, y = i / width;
|
|
||||||
int floorid = stream.readUnsignedByte();
|
|
||||||
int oreid = stream.readUnsignedByte();
|
|
||||||
int consecutives = stream.readUnsignedByte();
|
|
||||||
|
|
||||||
Tile tile = tiles.get(x, y);
|
|
||||||
tile.setFloor((Floor)idmap.get(floorid));
|
|
||||||
tile.setOverlay(idmap.get(oreid));
|
|
||||||
|
|
||||||
for(int j = i + 1; j < i + 1 + consecutives; j++){
|
|
||||||
int newx = j % width, newy = j / width;
|
|
||||||
Tile newTile = tiles.get(newx, newy);
|
|
||||||
newTile.setFloor((Floor)idmap.get(floorid));
|
|
||||||
newTile.setOverlay(idmap.get(oreid));
|
|
||||||
}
|
|
||||||
|
|
||||||
i += consecutives;
|
|
||||||
}
|
|
||||||
|
|
||||||
//read blocks
|
|
||||||
for(int i = 0; i < width * height; i++){
|
|
||||||
int x = i % width, y = i / width;
|
|
||||||
int id = stream.readUnsignedByte();
|
|
||||||
Block block = idmap.get(id);
|
|
||||||
if(block == null) block = Blocks.air;
|
|
||||||
|
|
||||||
Tile tile = tiles.get(x, y);
|
|
||||||
//the spawn block is saved in the block tile layer in older maps, shift it to the overlay
|
|
||||||
if(block != Blocks.spawn){
|
|
||||||
tile.setBlock(block);
|
|
||||||
}else{
|
|
||||||
tile.setOverlay(block);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(namemap.get(id, "").equals("part")){
|
|
||||||
stream.readByte(); //link
|
|
||||||
}else if(tile.entity != null){
|
|
||||||
byte tr = stream.readByte();
|
|
||||||
stream.readShort(); //read health (which is actually irrelevant)
|
|
||||||
|
|
||||||
byte team = Pack.leftByte(tr);
|
|
||||||
byte rotation = Pack.rightByte(tr);
|
|
||||||
|
|
||||||
tile.setTeam(Team.all[team]);
|
|
||||||
tile.entity.health = tile.block().health;
|
|
||||||
tile.rotation(rotation);
|
|
||||||
|
|
||||||
if(tile.block() == Blocks.liquidSource || tile.block() == Blocks.unloader || tile.block() == Blocks.sorter){
|
|
||||||
stream.readByte(); //these blocks have an extra config byte, read it
|
|
||||||
}
|
|
||||||
}else{ //no entity/part, read consecutives
|
|
||||||
int consecutives = stream.readUnsignedByte();
|
|
||||||
|
|
||||||
for(int j = i + 1; j < i + 1 + consecutives; j++){
|
|
||||||
int newx = j % width, newy = j / width;
|
|
||||||
tiles.get(newx, newy).setBlock(block);
|
|
||||||
}
|
|
||||||
|
|
||||||
i += consecutives;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}finally{
|
|
||||||
content.setTemporaryMapper(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Reads a pixmap in the 3.5 pixmap format. */
|
|
||||||
public static void readPixmap(Pixmap pixmap, Tile[][] tiles){
|
|
||||||
for(int x = 0; x < pixmap.getWidth(); x++){
|
|
||||||
for(int y = 0; y < pixmap.getHeight(); y++){
|
|
||||||
int color = pixmap.getPixel(x, pixmap.getHeight() - 1 - y);
|
|
||||||
LegacyBlock block = LegacyColorMapper.get(color);
|
|
||||||
Tile tile = tiles[x][y];
|
|
||||||
|
|
||||||
tile.setFloor(block.floor);
|
|
||||||
tile.setBlock(block.wall);
|
|
||||||
if(block.ore != null) tile.setOverlay(block.ore);
|
|
||||||
|
|
||||||
//place core
|
|
||||||
if(color == Color.rgba8888(Color.green)){
|
|
||||||
//actual core parts
|
|
||||||
tile.setBlock(Blocks.coreShard);
|
|
||||||
tile.setTeam(Team.sharded);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -10,6 +10,7 @@ import mindustry.core.*;
|
|||||||
import mindustry.game.*;
|
import mindustry.game.*;
|
||||||
import mindustry.maps.*;
|
import mindustry.maps.*;
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
|
import mindustry.world.LegacyColorMapper.*;
|
||||||
import mindustry.world.blocks.storage.*;
|
import mindustry.world.blocks.storage.*;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
@@ -91,7 +92,7 @@ public class MapIO{
|
|||||||
public void setTeam(Team team){
|
public void setTeam(Team team){
|
||||||
super.setTeam(team);
|
super.setTeam(team);
|
||||||
if(block instanceof CoreBlock){
|
if(block instanceof CoreBlock){
|
||||||
map.teams.add(team.ordinal());
|
map.teams.add(team.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -145,11 +146,33 @@ public class MapIO{
|
|||||||
|
|
||||||
public static int colorFor(Block floor, Block wall, Block ore, Team team){
|
public static int colorFor(Block floor, Block wall, Block ore, Team team){
|
||||||
if(wall.synthetic()){
|
if(wall.synthetic()){
|
||||||
return team.intColor;
|
return team.color.rgba();
|
||||||
}
|
}
|
||||||
return Color.rgba8888(wall.solid ? wall.color : ore == Blocks.air ? floor.color : ore.color);
|
return Color.rgba8888(wall.solid ? wall.color : ore == Blocks.air ? floor.color : ore.color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Reads a pixmap in the 3.5 pixmap format. */
|
||||||
|
public static void readPixmap(Pixmap pixmap, Tile[][] tiles){
|
||||||
|
for(int x = 0; x < pixmap.getWidth(); x++){
|
||||||
|
for(int y = 0; y < pixmap.getHeight(); y++){
|
||||||
|
int color = pixmap.getPixel(x, pixmap.getHeight() - 1 - y);
|
||||||
|
LegacyBlock block = LegacyColorMapper.get(color);
|
||||||
|
Tile tile = tiles[x][y];
|
||||||
|
|
||||||
|
tile.setFloor(block.floor);
|
||||||
|
tile.setBlock(block.wall);
|
||||||
|
if(block.ore != null) tile.setOverlay(block.ore);
|
||||||
|
|
||||||
|
//place core
|
||||||
|
if(color == Color.rgba8888(Color.green)){
|
||||||
|
//actual core parts
|
||||||
|
tile.setBlock(Blocks.coreShard);
|
||||||
|
tile.setTeam(Team.sharded);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
interface TileProvider{
|
interface TileProvider{
|
||||||
Tile get(int x, int y);
|
Tile get(int x, int y);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -217,7 +217,7 @@ public abstract class SaveVersion extends SaveFileReader{
|
|||||||
Array<TeamData> data = state.teams.getActive();
|
Array<TeamData> data = state.teams.getActive();
|
||||||
stream.writeInt(data.size);
|
stream.writeInt(data.size);
|
||||||
for(TeamData team : data){
|
for(TeamData team : data){
|
||||||
stream.writeInt(team.team.ordinal());
|
stream.writeInt((int)team.team.id);
|
||||||
stream.writeInt(team.brokenBlocks.size);
|
stream.writeInt(team.brokenBlocks.size);
|
||||||
for(BrokenBlock block : team.brokenBlocks){
|
for(BrokenBlock block : team.brokenBlocks){
|
||||||
stream.writeShort(block.x);
|
stream.writeShort(block.x);
|
||||||
@@ -258,8 +258,8 @@ public abstract class SaveVersion extends SaveFileReader{
|
|||||||
public void readEntities(DataInput stream) throws IOException{
|
public void readEntities(DataInput stream) throws IOException{
|
||||||
int teamc = stream.readInt();
|
int teamc = stream.readInt();
|
||||||
for(int i = 0; i < teamc; i++){
|
for(int i = 0; i < teamc; i++){
|
||||||
Team team = Team.all[stream.readInt()];
|
Team team = Team.get(stream.readInt());
|
||||||
TeamData data = state.teams.get(team);
|
TeamData data = team.data();
|
||||||
int blocks = stream.readInt();
|
int blocks = stream.readInt();
|
||||||
for(int j = 0; j < blocks; j++){
|
for(int j = 0; j < blocks; j++){
|
||||||
data.brokenBlocks.addLast(new BrokenBlock(stream.readShort(), stream.readShort(), stream.readShort(), content.block(stream.readShort()).id, stream.readInt()));
|
data.brokenBlocks.addLast(new BrokenBlock(stream.readShort(), stream.readShort(), stream.readShort(), content.block(stream.readShort()).id, stream.readInt()));
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ public class TypeIO{
|
|||||||
|
|
||||||
@WriteClass(BaseUnit.class)
|
@WriteClass(BaseUnit.class)
|
||||||
public static void writeBaseUnit(ByteBuffer buffer, BaseUnit unit){
|
public static void writeBaseUnit(ByteBuffer buffer, BaseUnit unit){
|
||||||
buffer.put((byte)unit.getTeam().ordinal());
|
buffer.put((byte) (int)unit.getTeam().id);
|
||||||
buffer.putInt(unit.getID());
|
buffer.putInt(unit.getID());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,7 +95,7 @@ public class TypeIO{
|
|||||||
public static BaseUnit readBaseUnit(ByteBuffer buffer){
|
public static BaseUnit readBaseUnit(ByteBuffer buffer){
|
||||||
byte tid = buffer.get();
|
byte tid = buffer.get();
|
||||||
int id = buffer.getInt();
|
int id = buffer.getInt();
|
||||||
return unitGroups[tid].getByID(id);
|
return unitGroup.getByID(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@WriteClass(Tile.class)
|
@WriteClass(Tile.class)
|
||||||
@@ -194,12 +194,12 @@ public class TypeIO{
|
|||||||
|
|
||||||
@WriteClass(Team.class)
|
@WriteClass(Team.class)
|
||||||
public static void writeTeam(ByteBuffer buffer, Team reason){
|
public static void writeTeam(ByteBuffer buffer, Team reason){
|
||||||
buffer.put((byte)reason.ordinal());
|
buffer.put((byte) (int)reason.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ReadClass(Team.class)
|
@ReadClass(Team.class)
|
||||||
public static Team readTeam(ByteBuffer buffer){
|
public static Team readTeam(ByteBuffer buffer){
|
||||||
return Team.all[buffer.get()];
|
return Team.get(buffer.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
@WriteClass(UnitCommand.class)
|
@WriteClass(UnitCommand.class)
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ public class MapGenerator extends Generator{
|
|||||||
|
|
||||||
for(int x = 0; x < width; x++){
|
for(int x = 0; x < width; x++){
|
||||||
for(int y = 0; y < height; y++){
|
for(int y = 0; y < height; y++){
|
||||||
if(tiles[x][y].block() instanceof CoreBlock && tiles[x][y].getTeam() == defaultTeam){
|
if(tiles[x][y].block() instanceof CoreBlock && tiles[x][y].getTeam() == state.rules.defaultTeam){
|
||||||
players.add(new Point2(x, y));
|
players.add(new Point2(x, y));
|
||||||
tiles[x][y].setBlock(Blocks.air);
|
tiles[x][y].setBlock(Blocks.air);
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -2,7 +2,6 @@ package mindustry.mod;
|
|||||||
|
|
||||||
import arc.*;
|
import arc.*;
|
||||||
import arc.assets.*;
|
import arc.assets.*;
|
||||||
import arc.struct.*;
|
|
||||||
import arc.files.*;
|
import arc.files.*;
|
||||||
import arc.func.*;
|
import arc.func.*;
|
||||||
import arc.graphics.*;
|
import arc.graphics.*;
|
||||||
@@ -10,6 +9,7 @@ import arc.graphics.Texture.*;
|
|||||||
import arc.graphics.g2d.*;
|
import arc.graphics.g2d.*;
|
||||||
import arc.graphics.g2d.TextureAtlas.*;
|
import arc.graphics.g2d.TextureAtlas.*;
|
||||||
import arc.scene.ui.*;
|
import arc.scene.ui.*;
|
||||||
|
import arc.struct.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
import arc.util.ArcAnnotate.*;
|
import arc.util.ArcAnnotate.*;
|
||||||
import arc.util.io.*;
|
import arc.util.io.*;
|
||||||
@@ -85,6 +85,7 @@ public class Mods implements Loadable{
|
|||||||
try{
|
try{
|
||||||
mods.add(loadMod(dest));
|
mods.add(loadMod(dest));
|
||||||
requiresReload = true;
|
requiresReload = true;
|
||||||
|
sortMods();
|
||||||
}catch(IOException e){
|
}catch(IOException e){
|
||||||
dest.delete();
|
dest.delete();
|
||||||
throw e;
|
throw e;
|
||||||
@@ -142,6 +143,17 @@ public class Mods implements Loadable{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void loadSync(){
|
public void loadSync(){
|
||||||
|
for(LoadedMod mod : mods){
|
||||||
|
//try to load icon for each mod that can have one
|
||||||
|
if(mod.root.child("icon.png").exists()){
|
||||||
|
try{
|
||||||
|
mod.iconTexture = new Texture(mod.root.child("icon.png"));
|
||||||
|
}catch(Throwable t){
|
||||||
|
Log.err("Failed to load icon for mod '" + mod.name + "'.", t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(packer == null) return;
|
if(packer == null) return;
|
||||||
Time.mark();
|
Time.mark();
|
||||||
|
|
||||||
@@ -408,6 +420,7 @@ public class Mods implements Loadable{
|
|||||||
//TODO make it less epic
|
//TODO make it less epic
|
||||||
Core.atlas = new TextureAtlas(Core.files.internal("sprites/sprites.atlas"));
|
Core.atlas = new TextureAtlas(Core.files.internal("sprites/sprites.atlas"));
|
||||||
|
|
||||||
|
mods.each(LoadedMod::dispose);
|
||||||
mods.clear();
|
mods.clear();
|
||||||
Core.bundle = I18NBundle.createBundle(Core.files.internal("bundles/bundle"), Core.bundle.getLocale());
|
Core.bundle = I18NBundle.createBundle(Core.files.internal("bundles/bundle"), Core.bundle.getLocale());
|
||||||
load();
|
load();
|
||||||
@@ -643,7 +656,7 @@ public class Mods implements Loadable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Represents a plugin that has been loaded from a jar file.*/
|
/** Represents a plugin that has been loaded from a jar file.*/
|
||||||
public static class LoadedMod implements Publishable{
|
public static class LoadedMod implements Publishable, Disposable{
|
||||||
/** The location of this mod's zip file/folder on the disk. */
|
/** The location of this mod's zip file/folder on the disk. */
|
||||||
public final Fi file;
|
public final Fi file;
|
||||||
/** The root zip file; points to the contents of this mod. In the case of folders, this is the same as the mod's file. */
|
/** The root zip file; points to the contents of this mod. In the case of folders, this is the same as the mod's file. */
|
||||||
@@ -664,6 +677,8 @@ public class Mods implements Loadable{
|
|||||||
public ObjectSet<Content> erroredContent = new ObjectSet<>();
|
public ObjectSet<Content> erroredContent = new ObjectSet<>();
|
||||||
/** Current state of this mod. */
|
/** Current state of this mod. */
|
||||||
public ModState state = ModState.enabled;
|
public ModState state = ModState.enabled;
|
||||||
|
/** Icon texture. Should be disposed. */
|
||||||
|
public @Nullable Texture iconTexture;
|
||||||
|
|
||||||
public LoadedMod(Fi file, Fi root, Mod main, ModMeta meta){
|
public LoadedMod(Fi file, Fi root, Mod main, ModMeta meta){
|
||||||
this.root = root;
|
this.root = root;
|
||||||
@@ -701,6 +716,13 @@ public class Mods implements Loadable{
|
|||||||
return Version.build >= Strings.parseInt(meta.minGameVersion, 0);
|
return Version.build >= Strings.parseInt(meta.minGameVersion, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dispose(){
|
||||||
|
if(iconTexture != null){
|
||||||
|
iconTexture.dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getSteamID(){
|
public String getSteamID(){
|
||||||
return Core.settings.getString(name + "-steamid", null);
|
return Core.settings.getString(name + "-steamid", null);
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
package mindustry.net;
|
package mindustry.net;
|
||||||
|
|
||||||
import arc.*;
|
import arc.*;
|
||||||
import mindustry.annotations.Annotations.*;
|
|
||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
import mindustry.Vars;
|
import arc.util.ArcAnnotate.*;
|
||||||
|
import mindustry.*;
|
||||||
|
import mindustry.annotations.Annotations.*;
|
||||||
|
import mindustry.entities.type.*;
|
||||||
|
|
||||||
import static mindustry.Vars.headless;
|
import static mindustry.Vars.headless;
|
||||||
import static mindustry.game.EventType.*;
|
import static mindustry.game.EventType.*;
|
||||||
@@ -14,6 +15,7 @@ public class Administration{
|
|||||||
private ObjectMap<String, PlayerInfo> playerInfo = new ObjectMap<>();
|
private ObjectMap<String, PlayerInfo> playerInfo = new ObjectMap<>();
|
||||||
private Array<String> bannedIPs = new Array<>();
|
private Array<String> bannedIPs = new Array<>();
|
||||||
private Array<String> whitelist = new Array<>();
|
private Array<String> whitelist = new Array<>();
|
||||||
|
private Array<ChatFilter> chatFilters = new Array<>();
|
||||||
|
|
||||||
public Administration(){
|
public Administration(){
|
||||||
Core.settings.defaults(
|
Core.settings.defaults(
|
||||||
@@ -24,6 +26,23 @@ public class Administration{
|
|||||||
load();
|
load();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Adds a chat filter. This will transform the chat messages of every player.
|
||||||
|
* This functionality can be used to implement things like swear filters and special commands.
|
||||||
|
* Note that commands (starting with /) are not filtered.*/
|
||||||
|
public void addChatFilter(ChatFilter filter){
|
||||||
|
chatFilters.add(filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Filters out a chat message. */
|
||||||
|
public @Nullable String filterMessage(Player player, String message){
|
||||||
|
String current = message;
|
||||||
|
for(ChatFilter f : chatFilters){
|
||||||
|
current = f.filter(player, message);
|
||||||
|
if(current == null) return null;
|
||||||
|
}
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
public int getPlayerLimit(){
|
public int getPlayerLimit(){
|
||||||
return Core.settings.getInt("playerlimit", 0);
|
return Core.settings.getInt("playerlimit", 0);
|
||||||
}
|
}
|
||||||
@@ -334,6 +353,11 @@ public class Administration{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface ChatFilter{
|
||||||
|
/** @return the filtered message; a null string signals that the message should not be sent. */
|
||||||
|
@Nullable String filter(Player player, String message);
|
||||||
|
}
|
||||||
|
|
||||||
public static class TraceInfo{
|
public static class TraceInfo{
|
||||||
public String ip, uuid;
|
public String ip, uuid;
|
||||||
public boolean modded, mobile;
|
public boolean modded, mobile;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import arc.util.pooling.*;
|
|||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
|
|
||||||
public class Bar extends Element{
|
public class Bar extends Element{
|
||||||
private static Rectangle scissor = new Rectangle();
|
private static Rect scissor = new Rect();
|
||||||
|
|
||||||
private Floatp fraction;
|
private Floatp fraction;
|
||||||
private String name = "";
|
private String name = "";
|
||||||
|
|||||||
@@ -39,9 +39,9 @@ public class ItemsDisplay extends Table{
|
|||||||
private String format(Item item){
|
private String format(Item item){
|
||||||
builder.setLength(0);
|
builder.setLength(0);
|
||||||
builder.append(ui.formatAmount(data.items().get(item, 0)));
|
builder.append(ui.formatAmount(data.items().get(item, 0)));
|
||||||
if(!state.is(State.menu) && !state.teams.get(player.getTeam()).cores.isEmpty() && state.teams.get(player.getTeam()).cores.first().entity != null && state.teams.get(player.getTeam()).cores.first().entity.items.get(item) > 0){
|
if(!state.is(State.menu) && player.getTeam().data().hasCore() && player.getTeam().core().items.get(item) > 0){
|
||||||
builder.append(" [unlaunched]+ ");
|
builder.append(" [unlaunched]+ ");
|
||||||
builder.append(ui.formatAmount(state.teams.get(player.getTeam()).cores.first().entity.items.get(item)));
|
builder.append(ui.formatAmount(state.teams.get(player.getTeam()).core().items.get(item)));
|
||||||
}
|
}
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ public class DeployDialog extends FloatingDialog{
|
|||||||
private final float nodeSize = Scl.scl(230f);
|
private final float nodeSize = Scl.scl(230f);
|
||||||
private ObjectSet<ZoneNode> nodes = new ObjectSet<>();
|
private ObjectSet<ZoneNode> nodes = new ObjectSet<>();
|
||||||
private ZoneInfoDialog info = new ZoneInfoDialog();
|
private ZoneInfoDialog info = new ZoneInfoDialog();
|
||||||
private Rectangle bounds = new Rectangle();
|
private Rect bounds = new Rect();
|
||||||
private View view = new View();
|
private View view = new View();
|
||||||
|
|
||||||
public DeployDialog(){
|
public DeployDialog(){
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ public class TechTreeDialog extends FloatingDialog{
|
|||||||
private final float nodeSize = Scl.scl(60f);
|
private final float nodeSize = Scl.scl(60f);
|
||||||
private ObjectSet<TechTreeNode> nodes = new ObjectSet<>();
|
private ObjectSet<TechTreeNode> nodes = new ObjectSet<>();
|
||||||
private TechTreeNode root = new TechTreeNode(TechTree.root, null);
|
private TechTreeNode root = new TechTreeNode(TechTree.root, null);
|
||||||
private Rectangle bounds = new Rectangle();
|
private Rect bounds = new Rect();
|
||||||
private ItemsDisplay items;
|
private ItemsDisplay items;
|
||||||
private View view;
|
private View view;
|
||||||
|
|
||||||
@@ -123,7 +123,7 @@ public class TechTreeDialog extends FloatingDialog{
|
|||||||
miny = Math.min(n.y - n.height/2f, miny);
|
miny = Math.min(n.y - n.height/2f, miny);
|
||||||
maxy = Math.max(n.y + n.height/2f, maxy);
|
maxy = Math.max(n.y + n.height/2f, maxy);
|
||||||
}
|
}
|
||||||
bounds = new Rectangle(minx, miny, maxx - minx, maxy - miny);
|
bounds = new Rect(minx, miny, maxx - minx, maxy - miny);
|
||||||
bounds.y += nodeSize*1.5f;
|
bounds.y += nodeSize*1.5f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -168,7 +168,7 @@ public class HudFragment extends Fragment{
|
|||||||
t.table(teams -> {
|
t.table(teams -> {
|
||||||
teams.left();
|
teams.left();
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for(Team team : Team.all){
|
for(Team team : Team.base()){
|
||||||
ImageButton button = teams.addImageButton(Tex.whiteui, Styles.clearTogglePartiali, 40f, () -> Call.setPlayerTeamEditor(player, team))
|
ImageButton button = teams.addImageButton(Tex.whiteui, Styles.clearTogglePartiali, 40f, () -> Call.setPlayerTeamEditor(player, team))
|
||||||
.size(50f).margin(6f).get();
|
.size(50f).margin(6f).get();
|
||||||
button.getImageCell().grow();
|
button.getImageCell().grow();
|
||||||
@@ -287,7 +287,7 @@ public class HudFragment extends Fragment{
|
|||||||
});
|
});
|
||||||
|
|
||||||
t.top().visible(() -> {
|
t.top().visible(() -> {
|
||||||
if(state.is(State.menu) || state.teams.get(player.getTeam()).cores.size == 0 || state.teams.get(player.getTeam()).cores.first().entity == null){
|
if(state.is(State.menu) || !state.teams.get(player.getTeam()).hasCore()){
|
||||||
coreAttackTime[0] = 0f;
|
coreAttackTime[0] = 0f;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -557,7 +557,7 @@ public class HudFragment extends Fragment{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean canLaunch(){
|
private boolean canLaunch(){
|
||||||
return inLaunchWave() && state.enemies() <= 0;
|
return inLaunchWave() && state.enemies <= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void toggleMenus(){
|
private void toggleMenus(){
|
||||||
@@ -604,7 +604,7 @@ public class HudFragment extends Fragment{
|
|||||||
|
|
||||||
if(inLaunchWave()){
|
if(inLaunchWave()){
|
||||||
builder.append("[#");
|
builder.append("[#");
|
||||||
Tmp.c1.set(Color.white).lerp(state.enemies() > 0 ? Color.white : Color.scarlet, Mathf.absin(Time.time(), 2f, 1f)).toString(builder);
|
Tmp.c1.set(Color.white).lerp(state.enemies > 0 ? Color.white : Color.scarlet, Mathf.absin(Time.time(), 2f, 1f)).toString(builder);
|
||||||
builder.append("]");
|
builder.append("]");
|
||||||
|
|
||||||
if(!canLaunch()){
|
if(!canLaunch()){
|
||||||
@@ -618,18 +618,18 @@ public class HudFragment extends Fragment{
|
|||||||
builder.append("[]\n");
|
builder.append("[]\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(state.enemies() > 0){
|
if(state.enemies > 0){
|
||||||
if(state.enemies() == 1){
|
if(state.enemies == 1){
|
||||||
builder.append(enemyf.get(state.enemies()));
|
builder.append(enemyf.get(state.enemies));
|
||||||
}else{
|
}else{
|
||||||
builder.append(enemiesf.get(state.enemies()));
|
builder.append(enemiesf.get(state.enemies));
|
||||||
}
|
}
|
||||||
builder.append("\n");
|
builder.append("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if(state.rules.waveTimer){
|
if(state.rules.waveTimer){
|
||||||
builder.append((state.rules.waitForWaveToEnd && unitGroups[waveTeam.ordinal()].size() > 0) ? Core.bundle.get("wave.waveInProgress") : ( waitingf.get((int)(state.wavetime/60))));
|
builder.append((state.rules.waitForWaveToEnd && state.enemies > 0 ? Core.bundle.get("wave.waveInProgress") : ( waitingf.get((int)(state.wavetime/60)))));
|
||||||
}else if(state.enemies() == 0){
|
}else if(state.enemies == 0){
|
||||||
builder.append(Core.bundle.get("waiting"));
|
builder.append(Core.bundle.get("waiting"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -646,7 +646,7 @@ public class HudFragment extends Fragment{
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean canSkipWave(){
|
private boolean canSkipWave(){
|
||||||
return state.rules.waves && ((net.server() || player.isAdmin) || !net.active()) && state.enemies() == 0 && !spawner.isSpawning() && !state.rules.tutorial;
|
return state.rules.waves && ((net.server() || player.isAdmin) || !net.active()) && state.enemies == 0 && !spawner.isSpawning() && !state.rules.tutorial;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addPlayButton(Table table){
|
private void addPlayButton(Table table){
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import arc.scene.ui.*;
|
|||||||
import arc.scene.ui.layout.*;
|
import arc.scene.ui.layout.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
import mindustry.core.GameState.*;
|
import mindustry.core.GameState.*;
|
||||||
|
import mindustry.entities.type.*;
|
||||||
import mindustry.gen.*;
|
import mindustry.gen.*;
|
||||||
import mindustry.graphics.*;
|
import mindustry.graphics.*;
|
||||||
import mindustry.net.*;
|
import mindustry.net.*;
|
||||||
@@ -65,7 +66,7 @@ public class PlayerListFragment extends Fragment{
|
|||||||
|
|
||||||
float h = 74f;
|
float h = 74f;
|
||||||
|
|
||||||
playerGroup.all().sort((p1, p2) -> p1.getTeam().compareTo(p2.getTeam()));
|
playerGroup.all().sort(Structs.comparing(Unit::getTeam));
|
||||||
playerGroup.all().each(user -> {
|
playerGroup.all().each(user -> {
|
||||||
NetConnection connection = user.con;
|
NetConnection connection = user.con;
|
||||||
|
|
||||||
|
|||||||
@@ -66,8 +66,8 @@ public class BranchTreeLayout implements TreeLayout{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Rectangle getBounds(){
|
public Rect getBounds(){
|
||||||
return new Rectangle(boundsLeft, boundsBottom, boundsRight - boundsLeft, boundsTop - boundsBottom);
|
return new Rect(boundsLeft, boundsBottom, boundsRight - boundsLeft, boundsTop - boundsBottom);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void calcSizeOfLevels(TreeNode node, int level){
|
private void calcSizeOfLevels(TreeNode node, int level){
|
||||||
|
|||||||
@@ -866,7 +866,7 @@ public class Block extends BlockStorage{
|
|||||||
return ((size + 1) % 2) * tilesize / 2f;
|
return ((size + 1) % 2) * tilesize / 2f;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Rectangle bounds(int x, int y, Rectangle rect){
|
public Rect bounds(int x, int y, Rect rect){
|
||||||
return rect.setSize(size * tilesize).setCenter(x * tilesize + offset(), y * tilesize + offset());
|
return rect.setSize(size * tilesize).setCenter(x * tilesize + offset(), y * tilesize + offset());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ public class Build{
|
|||||||
Block previous = tile.block();
|
Block previous = tile.block();
|
||||||
Block sub = BuildBlock.get(previous.size);
|
Block sub = BuildBlock.get(previous.size);
|
||||||
|
|
||||||
world.setBlock(tile, sub, team, rotation);
|
tile.set(sub, team, rotation);
|
||||||
tile.<BuildEntity>ent().setDeconstruct(previous);
|
tile.<BuildEntity>ent().setDeconstruct(previous);
|
||||||
tile.entity.health = tile.entity.maxHealth() * prevPercent;
|
tile.entity.health = tile.entity.maxHealth() * prevPercent;
|
||||||
|
|
||||||
@@ -60,7 +60,7 @@ public class Build{
|
|||||||
Block previous = tile.block();
|
Block previous = tile.block();
|
||||||
Block sub = BuildBlock.get(result.size);
|
Block sub = BuildBlock.get(result.size);
|
||||||
|
|
||||||
world.setBlock(tile, sub, team, rotation);
|
tile.set(sub, team, rotation);
|
||||||
tile.<BuildEntity>ent().setConstruct(previous, result);
|
tile.<BuildEntity>ent().setConstruct(previous, result);
|
||||||
|
|
||||||
Core.app.post(() -> Events.fire(new BlockBuildBeginEvent(tile, team, false)));
|
Core.app.post(() -> Events.fire(new BlockBuildBeginEvent(tile, team, false)));
|
||||||
@@ -72,7 +72,7 @@ public class Build{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(state.rules.bannedBlocks.contains(type) && !(state.rules.waves && team == waveTeam)){
|
if(state.rules.bannedBlocks.contains(type) && !(state.rules.waves && team == state.rules.waveTeam)){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,13 +80,8 @@ public class Build{
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//check for enemy cores
|
if(state.teams.eachEnemyCore(team, core -> Mathf.dst(x * tilesize + type.offset(), y * tilesize + type.offset(), core.x, core.y) < state.rules.enemyCoreBuildRadius + type.size * tilesize / 2f)){
|
||||||
for(Team enemy : state.teams.enemiesOf(team)){
|
return false;
|
||||||
for(Tile core : state.teams.get(enemy).cores){
|
|
||||||
if(Mathf.dst(x * tilesize + type.offset(), y * tilesize + type.offset(), core.drawx(), core.drawy()) < state.rules.enemyCoreBuildRadius + type.size * tilesize / 2f){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Tile tile = world.tile(x, y);
|
Tile tile = world.tile(x, y);
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public class CachedTile extends Tile{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Team getTeam(){
|
public Team getTeam(){
|
||||||
return Team.all[getTeamID()];
|
return Team.get(getTeamID());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -142,11 +142,11 @@ public class Tile implements Position, TargetTrait{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Team getTeam(){
|
public Team getTeam(){
|
||||||
return Team.all[link().team];
|
return Team.get(link().team);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTeam(Team team){
|
public void setTeam(Team team){
|
||||||
this.team = (byte)team.ordinal();
|
this.team = (byte) team.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte getTeamID(){
|
public byte getTeamID(){
|
||||||
@@ -156,7 +156,7 @@ public class Tile implements Position, TargetTrait{
|
|||||||
public void setBlock(@NonNull Block type, Team team, int rotation){
|
public void setBlock(@NonNull Block type, Team team, int rotation){
|
||||||
preChanged();
|
preChanged();
|
||||||
this.block = type;
|
this.block = type;
|
||||||
this.team = (byte)team.ordinal();
|
this.team = (byte) team.id;
|
||||||
this.rotation = (byte)Mathf.mod(rotation, 4);
|
this.rotation = (byte)Mathf.mod(rotation, 4);
|
||||||
changed();
|
changed();
|
||||||
}
|
}
|
||||||
@@ -186,6 +186,35 @@ public class Tile implements Position, TargetTrait{
|
|||||||
setOverlay(overlay);
|
setOverlay(overlay);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void remove(){
|
||||||
|
link().getLinkedTiles(other -> other.setBlock(Blocks.air));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(Block block, Team team){
|
||||||
|
set(block, team, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(Block block, Team team, int rotation){
|
||||||
|
setBlock(block, team, rotation);
|
||||||
|
if(block.isMultiblock()){
|
||||||
|
int offsetx = -(block.size - 1) / 2;
|
||||||
|
int offsety = -(block.size - 1) / 2;
|
||||||
|
|
||||||
|
for(int dx = 0; dx < block.size; dx++){
|
||||||
|
for(int dy = 0; dy < block.size; dy++){
|
||||||
|
int worldx = dx + offsetx + x;
|
||||||
|
int worldy = dy + offsety + y;
|
||||||
|
if(!(worldx == x && worldy == y)){
|
||||||
|
Tile toplace = world.tile(worldx, worldy);
|
||||||
|
if(toplace != null){
|
||||||
|
toplace.setBlock(BlockPart.get(dx + offsetx, dy + offsety), team);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public byte rotation(){
|
public byte rotation(){
|
||||||
return rotation;
|
return rotation;
|
||||||
}
|
}
|
||||||
@@ -240,7 +269,7 @@ public class Tile implements Position, TargetTrait{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isEnemyCheat(){
|
public boolean isEnemyCheat(){
|
||||||
return getTeam() == waveTeam && state.rules.enemyCheat;
|
return getTeam() == state.rules.waveTeam && state.rules.enemyCheat;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isLinked(){
|
public boolean isLinked(){
|
||||||
@@ -298,7 +327,7 @@ public class Tile implements Position, TargetTrait{
|
|||||||
return tmpArray;
|
return tmpArray;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Rectangle getHitbox(Rectangle rect){
|
public Rect getHitbox(Rect rect){
|
||||||
return rect.setSize(block().size * tilesize).setCenter(drawx(), drawy());
|
return rect.setSize(block().size * tilesize).setCenter(drawx(), drawy());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,7 +373,7 @@ public class Tile implements Position, TargetTrait{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean interactable(Team team){
|
public boolean interactable(Team team){
|
||||||
return getTeam() == Team.derelict || team == getTeam();
|
return state.teams.canInteract(team, getTeam());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Item drop(){
|
public Item drop(){
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ public class BuildBlock extends Block{
|
|||||||
public static void onDeconstructFinish(Tile tile, Block block, int builderID){
|
public static void onDeconstructFinish(Tile tile, Block block, int builderID){
|
||||||
Team team = tile.getTeam();
|
Team team = tile.getTeam();
|
||||||
Effects.effect(Fx.breakBlock, tile.drawx(), tile.drawy(), block.size);
|
Effects.effect(Fx.breakBlock, tile.drawx(), tile.drawy(), block.size);
|
||||||
world.removeBlock(tile);
|
tile.remove();
|
||||||
Events.fire(new BlockBuildEndEvent(tile, playerGroup.getByID(builderID), team, true));
|
Events.fire(new BlockBuildEndEvent(tile, playerGroup.getByID(builderID), team, true));
|
||||||
if(shouldPlay()) Sounds.breaks.at(tile, calcPitch(false));
|
if(shouldPlay()) Sounds.breaks.at(tile, calcPitch(false));
|
||||||
}
|
}
|
||||||
@@ -66,7 +66,7 @@ public class BuildBlock extends Block{
|
|||||||
public static void onConstructFinish(Tile tile, Block block, int builderID, byte rotation, Team team, boolean skipConfig){
|
public static void onConstructFinish(Tile tile, Block block, int builderID, byte rotation, Team team, boolean skipConfig){
|
||||||
if(tile == null) return;
|
if(tile == null) return;
|
||||||
float healthf = tile.entity == null ? 1f : tile.entity.healthf();
|
float healthf = tile.entity == null ? 1f : tile.entity.healthf();
|
||||||
world.setBlock(tile, block, team, rotation);
|
tile.set(block, team, rotation);
|
||||||
if(tile.entity != null){
|
if(tile.entity != null){
|
||||||
tile.entity.health = block.health * healthf;
|
tile.entity.health = block.health * healthf;
|
||||||
}
|
}
|
||||||
@@ -337,6 +337,7 @@ public class BuildBlock extends Block{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setDeconstruct(Block previous){
|
public void setDeconstruct(Block previous){
|
||||||
|
if(previous == null) return;
|
||||||
this.previous = previous;
|
this.previous = previous;
|
||||||
this.progress = 1f;
|
this.progress = 1f;
|
||||||
if(previous.buildCost >= 0.01f){
|
if(previous.buildCost >= 0.01f){
|
||||||
|
|||||||
@@ -43,9 +43,9 @@ public class StaticWall extends Rock{
|
|||||||
|
|
||||||
boolean eq(int rx, int ry){
|
boolean eq(int rx, int ry){
|
||||||
return rx < world.width() - 1 && ry < world.height() - 1
|
return rx < world.width() - 1 && ry < world.height() - 1
|
||||||
&& world.tile(rx + 1, ry).block() == this
|
&& world.tile(rx + 1, ry).block() == this
|
||||||
&& world.tile(rx, ry + 1).block() == this
|
&& world.tile(rx, ry + 1).block() == this
|
||||||
&& world.tile(rx, ry).block() == this
|
&& world.tile(rx, ry).block() == this
|
||||||
&& world.tile(rx + 1, ry + 1).block() == this;
|
&& world.tile(rx + 1, ry + 1).block() == this;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ public class DeflectorWall extends Wall{
|
|||||||
public static final float hitTime = 10f;
|
public static final float hitTime = 10f;
|
||||||
|
|
||||||
protected float maxDamageDeflect = 10f;
|
protected float maxDamageDeflect = 10f;
|
||||||
protected Rectangle rect = new Rectangle();
|
protected Rect rect = new Rect();
|
||||||
protected Rectangle rect2 = new Rectangle();
|
protected Rect rect2 = new Rect();
|
||||||
|
|
||||||
public DeflectorWall(String name){
|
public DeflectorWall(String name){
|
||||||
super(name);
|
super(name);
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import java.io.*;
|
|||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
|
|
||||||
public class Door extends Wall{
|
public class Door extends Wall{
|
||||||
protected final static Rectangle rect = new Rectangle();
|
protected final static Rect rect = new Rect();
|
||||||
|
|
||||||
public final int timerToggle = timers++;
|
public final int timerToggle = timers++;
|
||||||
public Effect openfx = Fx.dooropen;
|
public Effect openfx = Fx.dooropen;
|
||||||
|
|||||||
@@ -84,12 +84,12 @@ public class CoreBlock extends StorageBlock{
|
|||||||
public void onProximityUpdate(Tile tile){
|
public void onProximityUpdate(Tile tile){
|
||||||
CoreEntity entity = tile.ent();
|
CoreEntity entity = tile.ent();
|
||||||
|
|
||||||
for(Tile other : state.teams.get(tile.getTeam()).cores){
|
for(TileEntity other : state.teams.cores(tile.getTeam())){
|
||||||
if(other != tile){
|
if(other.tile != tile){
|
||||||
entity.items = other.entity.items;
|
entity.items = other.items;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
state.teams.get(tile.getTeam()).cores.add(tile);
|
state.teams.registerCore(entity);
|
||||||
|
|
||||||
entity.storageCapacity = itemCapacity + entity.proximity().sum(e -> isContainer(e) ? e.block().itemCapacity : 0);
|
entity.storageCapacity = itemCapacity + entity.proximity().sum(e -> isContainer(e) ? e.block().itemCapacity : 0);
|
||||||
entity.proximity().each(this::isContainer, t -> {
|
entity.proximity().each(this::isContainer, t -> {
|
||||||
@@ -97,9 +97,9 @@ public class CoreBlock extends StorageBlock{
|
|||||||
t.<StorageBlockEntity>ent().linkedCore = tile;
|
t.<StorageBlockEntity>ent().linkedCore = tile;
|
||||||
});
|
});
|
||||||
|
|
||||||
for(Tile other : state.teams.get(tile.getTeam()).cores){
|
for(TileEntity other : state.teams.cores(tile.getTeam())){
|
||||||
if(other == tile) continue;
|
if(other.tile == tile) continue;
|
||||||
entity.storageCapacity += other.block().itemCapacity + other.entity.proximity().sum(e -> isContainer(e) ? e.block().itemCapacity : 0);
|
entity.storageCapacity += other.block.itemCapacity + entity.proximity().sum(e -> isContainer(e) ? e.block().itemCapacity : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!world.isGenerating()){
|
if(!world.isGenerating()){
|
||||||
@@ -108,9 +108,8 @@ public class CoreBlock extends StorageBlock{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(Tile other : state.teams.get(tile.getTeam()).cores){
|
for(CoreEntity other : state.teams.cores(tile.getTeam())){
|
||||||
CoreEntity oe = other.ent();
|
other.storageCapacity = entity.storageCapacity;
|
||||||
oe.storageCapacity = entity.storageCapacity;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,8 +150,9 @@ public class CoreBlock extends StorageBlock{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removed(Tile tile){
|
public void removed(Tile tile){
|
||||||
|
CoreEntity entity = tile.ent();
|
||||||
int total = tile.entity.proximity().count(e -> e.entity.items == tile.entity.items);
|
int total = tile.entity.proximity().count(e -> e.entity.items == tile.entity.items);
|
||||||
float fract = 1f / total / state.teams.get(tile.getTeam()).cores.size;
|
float fract = 1f / total / state.teams.cores(tile.getTeam()).size;
|
||||||
|
|
||||||
tile.entity.proximity().each(e -> isContainer(e) && e.entity.items == tile.entity.items, t -> {
|
tile.entity.proximity().each(e -> isContainer(e) && e.entity.items == tile.entity.items, t -> {
|
||||||
StorageBlockEntity ent = (StorageBlockEntity)t.entity;
|
StorageBlockEntity ent = (StorageBlockEntity)t.entity;
|
||||||
@@ -163,22 +163,23 @@ public class CoreBlock extends StorageBlock{
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
state.teams.get(tile.getTeam()).cores.remove(tile);
|
state.teams.unregisterCore(entity);
|
||||||
|
|
||||||
int max = itemCapacity * state.teams.get(tile.getTeam()).cores.size;
|
int max = itemCapacity * state.teams.cores(tile.getTeam()).size;
|
||||||
for(Item item : content.items()){
|
for(Item item : content.items()){
|
||||||
tile.entity.items.set(item, Math.min(tile.entity.items.get(item), max));
|
tile.entity.items.set(item, Math.min(tile.entity.items.get(item), max));
|
||||||
}
|
}
|
||||||
|
|
||||||
for(Tile other : state.teams.get(tile.getTeam()).cores){
|
for(CoreEntity other : state.teams.cores(tile.getTeam())){
|
||||||
other.block().onProximityUpdate(other);
|
other.block.onProximityUpdate(other.tile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void placed(Tile tile){
|
public void placed(Tile tile){
|
||||||
super.placed(tile);
|
super.placed(tile);
|
||||||
state.teams.get(tile.getTeam()).cores.add(tile);
|
CoreEntity entity = tile.ent();
|
||||||
|
state.teams.registerCore(entity);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
package mindustry.world.blocks.units;
|
package mindustry.world.blocks.units;
|
||||||
|
|
||||||
import arc.*;
|
import arc.*;
|
||||||
import arc.struct.*;
|
|
||||||
import arc.graphics.*;
|
import arc.graphics.*;
|
||||||
import arc.graphics.g2d.*;
|
import arc.graphics.g2d.*;
|
||||||
import arc.scene.ui.*;
|
import arc.scene.ui.*;
|
||||||
import arc.scene.ui.layout.*;
|
import arc.scene.ui.layout.*;
|
||||||
|
import arc.struct.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
import mindustry.content.*;
|
import mindustry.content.*;
|
||||||
import mindustry.entities.*;
|
import mindustry.entities.*;
|
||||||
@@ -13,7 +13,6 @@ import mindustry.entities.Effects.*;
|
|||||||
import mindustry.entities.type.*;
|
import mindustry.entities.type.*;
|
||||||
import mindustry.entities.units.*;
|
import mindustry.entities.units.*;
|
||||||
import mindustry.game.EventType.*;
|
import mindustry.game.EventType.*;
|
||||||
import mindustry.game.*;
|
|
||||||
import mindustry.graphics.*;
|
import mindustry.graphics.*;
|
||||||
import mindustry.ui.*;
|
import mindustry.ui.*;
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
@@ -21,7 +20,7 @@ import mindustry.world.meta.*;
|
|||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
|
||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.indexer;
|
||||||
|
|
||||||
public class CommandCenter extends Block{
|
public class CommandCenter extends Block{
|
||||||
protected TextureRegion[] commandRegions = new TextureRegion[UnitCommand.all.length];
|
protected TextureRegion[] commandRegions = new TextureRegion[UnitCommand.all.length];
|
||||||
@@ -58,9 +57,7 @@ public class CommandCenter extends Block{
|
|||||||
ObjectSet<Tile> set = indexer.getAllied(tile.getTeam(), BlockFlag.comandCenter);
|
ObjectSet<Tile> set = indexer.getAllied(tile.getTeam(), BlockFlag.comandCenter);
|
||||||
|
|
||||||
if(set.size == 1){
|
if(set.size == 1){
|
||||||
for(BaseUnit unit : unitGroups[tile.getTeam().ordinal()].all()){
|
Units.each(tile.getTeam(), u -> u.onCommand(UnitCommand.all[0]));
|
||||||
unit.onCommand(UnitCommand.all[0]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,12 +111,7 @@ public class CommandCenter extends Block{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Team team = (player == null ? tile.getTeam() : player.getTeam());
|
Units.each(tile.getTeam(), u -> u.onCommand(command));
|
||||||
|
|
||||||
for(BaseUnit unit : unitGroups[team.ordinal()].all()){
|
|
||||||
unit.onCommand(command);
|
|
||||||
}
|
|
||||||
|
|
||||||
Events.fire(new CommandIssueEvent(tile, command));
|
Events.fire(new CommandIssueEvent(tile, command));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import arc.graphics.Color;
|
|||||||
import arc.graphics.g2d.*;
|
import arc.graphics.g2d.*;
|
||||||
import arc.math.Angles;
|
import arc.math.Angles;
|
||||||
import arc.math.Mathf;
|
import arc.math.Mathf;
|
||||||
import arc.math.geom.Rectangle;
|
import arc.math.geom.Rect;
|
||||||
import arc.util.Time;
|
import arc.util.Time;
|
||||||
import mindustry.entities.Units;
|
import mindustry.entities.Units;
|
||||||
import mindustry.entities.type.TileEntity;
|
import mindustry.entities.type.TileEntity;
|
||||||
@@ -19,7 +19,7 @@ import mindustry.world.meta.*;
|
|||||||
import static mindustry.Vars.tilesize;
|
import static mindustry.Vars.tilesize;
|
||||||
|
|
||||||
public class RepairPoint extends Block{
|
public class RepairPoint extends Block{
|
||||||
private static Rectangle rect = new Rectangle();
|
private static Rect rect = new Rect();
|
||||||
|
|
||||||
public int timerTarget = timers++;
|
public int timerTarget = timers++;
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ task run(dependsOn: classes, type: JavaExec){
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(args.contains("debug")){
|
if(args.contains("debug")){
|
||||||
main = "io.anuke.mindustry.DebugLauncher"
|
main = "mindustry.debug.DebugLauncher"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package mindustry.desktop.steam;
|
package mindustry.desktop.steam;
|
||||||
|
|
||||||
import arc.*;
|
import arc.*;
|
||||||
import com.codedisaster.steamworks.*;
|
|
||||||
import arc.struct.*;
|
import arc.struct.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
|
import com.codedisaster.steamworks.*;
|
||||||
import mindustry.*;
|
import mindustry.*;
|
||||||
import mindustry.content.*;
|
import mindustry.content.*;
|
||||||
import mindustry.entities.type.*;
|
import mindustry.entities.type.*;
|
||||||
@@ -11,7 +11,6 @@ import mindustry.entities.units.*;
|
|||||||
import mindustry.game.EventType.*;
|
import mindustry.game.EventType.*;
|
||||||
import mindustry.game.Stats.*;
|
import mindustry.game.Stats.*;
|
||||||
import mindustry.type.*;
|
import mindustry.type.*;
|
||||||
import mindustry.world.*;
|
|
||||||
|
|
||||||
import static mindustry.Vars.*;
|
import static mindustry.Vars.*;
|
||||||
import static mindustry.desktop.steam.SAchievement.*;
|
import static mindustry.desktop.steam.SAchievement.*;
|
||||||
@@ -55,18 +54,18 @@ public class SStats implements SteamUserStatsCallback{
|
|||||||
|
|
||||||
private void checkUpdate(){
|
private void checkUpdate(){
|
||||||
if(campaign()){
|
if(campaign()){
|
||||||
SStat.maxUnitActive.max(unitGroups[player.getTeam().ordinal()].size());
|
SStat.maxUnitActive.max(unitGroup.count(t -> t.getTeam() == player.getTeam()));
|
||||||
|
|
||||||
if(unitGroups[player.getTeam().ordinal()].count(u -> u.getType() == UnitTypes.phantom) >= 10){
|
if(unitGroup.count(u -> u.getType() == UnitTypes.phantom && u.getTeam() == player.getTeam()) >= 10){
|
||||||
active10Phantoms.complete();
|
active10Phantoms.complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
if(unitGroups[player.getTeam().ordinal()].count(u -> u.getType() == UnitTypes.crawler) >= 50){
|
if(unitGroup.count(u -> u.getType() == UnitTypes.crawler && u.getTeam() == player.getTeam()) >= 50){
|
||||||
active50Crawlers.complete();
|
active50Crawlers.complete();
|
||||||
}
|
}
|
||||||
|
|
||||||
for(Tile tile : state.teams.get(player.getTeam()).cores){
|
for(TileEntity entity : player.getTeam().cores()){
|
||||||
if(!content.items().contains(i -> i.type == ItemType.material && tile.entity.items.get(i) < tile.block().itemCapacity)){
|
if(!content.items().contains(i -> i.type == ItemType.material && entity.items.get(i) < entity.block.itemCapacity)){
|
||||||
fillCoreAllCampaign.complete();
|
fillCoreAllCampaign.complete();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
org.gradle.daemon=true
|
org.gradle.daemon=true
|
||||||
org.gradle.jvmargs=-Xms256m -Xmx1024m
|
org.gradle.jvmargs=-Xms256m -Xmx1024m
|
||||||
archash=88c1a9afe2f5be4dd06e47ac8afe070247b3da29
|
archash=60a9ebe264f92f2c3082596c77b9ab29474c4a7f
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ public class ServerControl implements ApplicationListener{
|
|||||||
if(state.rules.waves){
|
if(state.rules.waves){
|
||||||
info("&lcGame over! Reached wave &ly{0}&lc with &ly{1}&lc players online on map &ly{2}&lc.", state.wave, playerGroup.size(), Strings.capitalize(world.getMap().name()));
|
info("&lcGame over! Reached wave &ly{0}&lc with &ly{1}&lc players online on map &ly{2}&lc.", state.wave, playerGroup.size(), Strings.capitalize(world.getMap().name()));
|
||||||
}else{
|
}else{
|
||||||
info("&lcGame over! Team &ly{0}&lc is victorious with &ly{1}&lc players online on map &ly{2}&lc.", event.winner.name(), playerGroup.size(), Strings.capitalize(world.getMap().name()));
|
info("&lcGame over! Team &ly{0}&lc is victorious with &ly{1}&lc players online on map &ly{2}&lc.", event.winner.name, playerGroup.size(), Strings.capitalize(world.getMap().name()));
|
||||||
}
|
}
|
||||||
|
|
||||||
//set next map to be played
|
//set next map to be played
|
||||||
@@ -143,7 +143,7 @@ public class ServerControl implements ApplicationListener{
|
|||||||
nextMapOverride = null;
|
nextMapOverride = null;
|
||||||
if(map != null){
|
if(map != null){
|
||||||
Call.onInfoMessage((state.rules.pvp
|
Call.onInfoMessage((state.rules.pvp
|
||||||
? "[YELLOW]The " + event.winner.name() + " team is victorious![]" : "[SCARLET]Game over![]")
|
? "[YELLOW]The " + event.winner.name + " team is victorious![]" : "[SCARLET]Game over![]")
|
||||||
+ "\nNext selected map:[accent] " + map.name() + "[]"
|
+ "\nNext selected map:[accent] " + map.name() + "[]"
|
||||||
+ (map.tags.containsKey("author") && !map.tags.get("author").trim().isEmpty() ? " by[accent] " + map.author() + "[]" : "") + "." +
|
+ (map.tags.containsKey("author") && !map.tags.get("author").trim().isEmpty() ? " by[accent] " + map.author() + "[]" : "") + "." +
|
||||||
"\nNew game begins in " + roundExtraTime + "[] seconds.");
|
"\nNew game begins in " + roundExtraTime + "[] seconds.");
|
||||||
@@ -292,7 +292,7 @@ public class ServerControl implements ApplicationListener{
|
|||||||
info(" &lyPlaying on map &fi{0}&fb &lb/&ly Wave {1}", Strings.capitalize(world.getMap().name()), state.wave);
|
info(" &lyPlaying on map &fi{0}&fb &lb/&ly Wave {1}", Strings.capitalize(world.getMap().name()), state.wave);
|
||||||
|
|
||||||
if(state.rules.waves){
|
if(state.rules.waves){
|
||||||
info("&ly {0} enemies.", unitGroups[Team.crux.ordinal()].size());
|
info("&ly {0} enemies.", state.enemies);
|
||||||
}else{
|
}else{
|
||||||
info("&ly {0} seconds until next wave.", (int)(state.wavetime / 60));
|
info("&ly {0} seconds until next wave.", (int)(state.wavetime / 60));
|
||||||
}
|
}
|
||||||
@@ -418,24 +418,26 @@ public class ServerControl implements ApplicationListener{
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try{
|
Team team = arg.length == 0 ? Team.sharded : Structs.find(Team.all(), t -> t.name.equals(arg[0]));
|
||||||
Team team = arg.length == 0 ? Team.sharded : Team.valueOf(arg[0]);
|
|
||||||
|
|
||||||
if(state.teams.get(team).cores.isEmpty()){
|
if(team == null){
|
||||||
err("That team has no cores.");
|
err("No team with that name found.");
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
for(Item item : content.items()){
|
|
||||||
if(item.type == ItemType.material){
|
|
||||||
state.teams.get(team).cores.first().entity.items.set(item, state.teams.get(team).cores.first().block().itemCapacity);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
info("Core filled.");
|
|
||||||
}catch(IllegalArgumentException ignored){
|
|
||||||
err("No such team exists.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(state.teams.cores(team).isEmpty()){
|
||||||
|
err("That team has no cores.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(Item item : content.items()){
|
||||||
|
if(item.type == ItemType.material){
|
||||||
|
state.teams.cores(team).first().items.set(item, state.teams.cores(team).first().block.itemCapacity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
info("Core filled.");
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
handler.register("name", "[name...]", "Change the server display name.", arg -> {
|
handler.register("name", "[name...]", "Change the server display name.", arg -> {
|
||||||
|
|||||||
@@ -106,8 +106,8 @@ public class ApplicationTests{
|
|||||||
Time.update();
|
Time.update();
|
||||||
Time.update();
|
Time.update();
|
||||||
Time.setDeltaProvider(() -> 1f);
|
Time.setDeltaProvider(() -> 1f);
|
||||||
unitGroups[waveTeam.ordinal()].updateEvents();
|
unitGroup.update();
|
||||||
assertFalse(unitGroups[waveTeam.ordinal()].isEmpty(), "No enemies spawned.");
|
assertFalse(unitGroup.isEmpty(), "No enemies spawned.");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -128,7 +128,7 @@ public class ApplicationTests{
|
|||||||
createMap();
|
createMap();
|
||||||
int bx = 4;
|
int bx = 4;
|
||||||
int by = 4;
|
int by = 4;
|
||||||
world.setBlock(world.tile(bx, by), Blocks.coreShard, Team.sharded);
|
world.tile(bx, by).set(Blocks.coreShard, Team.sharded);
|
||||||
assertEquals(world.tile(bx, by).getTeam(), Team.sharded);
|
assertEquals(world.tile(bx, by).getTeam(), Team.sharded);
|
||||||
for(int x = bx - 1; x <= bx + 1; x++){
|
for(int x = bx - 1; x <= bx + 1; x++){
|
||||||
for(int y = by - 1; y <= by + 1; y++){
|
for(int y = by - 1; y <= by + 1; y++){
|
||||||
@@ -198,7 +198,7 @@ public class ApplicationTests{
|
|||||||
@Test
|
@Test
|
||||||
void save(){
|
void save(){
|
||||||
world.loadMap(testMap);
|
world.loadMap(testMap);
|
||||||
assertTrue(state.teams.get(defaultTeam).cores.size > 0);
|
assertTrue(state.teams.playerCores().size > 0);
|
||||||
SaveIO.save(saveDirectory.child("0.msav"));
|
SaveIO.save(saveDirectory.child("0.msav"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,7 +213,7 @@ public class ApplicationTests{
|
|||||||
|
|
||||||
assertEquals(world.width(), map.width);
|
assertEquals(world.width(), map.width);
|
||||||
assertEquals(world.height(), map.height);
|
assertEquals(world.height(), map.height);
|
||||||
assertTrue(state.teams.get(defaultTeam).cores.size > 0);
|
assertTrue(state.teams.playerCores().size > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -379,12 +379,12 @@ public class ApplicationTests{
|
|||||||
createMap();
|
createMap();
|
||||||
|
|
||||||
Tile core = world.tile(5, 5);
|
Tile core = world.tile(5, 5);
|
||||||
world.setBlock(core, Blocks.coreShard, Team.sharded);
|
core.set(Blocks.coreShard, Team.sharded);
|
||||||
for(Item item : content.items()){
|
for(Item item : content.items()){
|
||||||
core.entity.items.set(item, 3000);
|
core.entity.items.set(item, 3000);
|
||||||
}
|
}
|
||||||
|
|
||||||
assertEquals(core, state.teams.get(Team.sharded).cores.first());
|
assertEquals(core.entity, state.teams.get(Team.sharded).core());
|
||||||
}
|
}
|
||||||
|
|
||||||
void depositTest(Block block, Item item){
|
void depositTest(Block block, Item item){
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
|
import arc.util.*;
|
||||||
import mindustry.game.*;
|
import mindustry.game.*;
|
||||||
import mindustry.io.TypeIO;
|
import mindustry.io.*;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.*;
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.*;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
|
||||||
|
|
||||||
public class IOTests{
|
public class IOTests{
|
||||||
|
|
||||||
@@ -49,5 +49,23 @@ public class IOTests{
|
|||||||
assertEquals(rules.attackMode, res.attackMode);
|
assertEquals(rules.attackMode, res.attackMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void writeRules2(){
|
||||||
|
Rules rules = new Rules();
|
||||||
|
rules.attackMode = true;
|
||||||
|
rules.tags.put("blah", "bleh");
|
||||||
|
rules.buildSpeedMultiplier = 99.1f;
|
||||||
|
|
||||||
|
String str = JsonIO.write(rules);
|
||||||
|
Rules res = JsonIO.read(Rules.class, str);
|
||||||
|
|
||||||
|
assertEquals(rules.buildSpeedMultiplier, res.buildSpeedMultiplier);
|
||||||
|
assertEquals(rules.attackMode, res.attackMode);
|
||||||
|
assertEquals(rules.tags.get("blah"), res.tags.get("blah"));
|
||||||
|
|
||||||
|
String str2 = JsonIO.write(new Rules(){{
|
||||||
|
attackMode = true;
|
||||||
|
}});
|
||||||
|
Log.info(str2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ public class ZoneTests{
|
|||||||
if(tile.drop() != null){
|
if(tile.drop() != null){
|
||||||
resources.add(tile.drop());
|
resources.add(tile.drop());
|
||||||
}
|
}
|
||||||
if(tile.block() instanceof CoreBlock && tile.getTeam() == defaultTeam){
|
if(tile.block() instanceof CoreBlock && tile.getTeam() == state.rules.defaultTeam){
|
||||||
hasSpawnPoint = true;
|
hasSpawnPoint = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -69,7 +69,7 @@ public class ZoneTests{
|
|||||||
}
|
}
|
||||||
|
|
||||||
assertTrue(hasSpawnPoint, "Zone \"" + zone.name + "\" has no spawn points.");
|
assertTrue(hasSpawnPoint, "Zone \"" + zone.name + "\" has no spawn points.");
|
||||||
assertTrue(spawner.countSpawns() > 0 || (state.rules.attackMode && !state.teams.get(waveTeam).cores.isEmpty()), "Zone \"" + zone.name + "\" has no enemy spawn points: " + spawner.countSpawns());
|
assertTrue(spawner.countSpawns() > 0 || (state.rules.attackMode && state.teams.get(state.rules.waveTeam).hasCore()), "Zone \"" + zone.name + "\" has no enemy spawn points: " + spawner.countSpawns());
|
||||||
|
|
||||||
for(Item item : resources){
|
for(Item item : resources){
|
||||||
assertTrue(zone.resources.contains(item), "Zone \"" + zone.name + "\" is missing item in resource list: \"" + item.name + "\"");
|
assertTrue(zone.resources.contains(item), "Zone \"" + zone.name + "\" is missing item in resource list: \"" + item.name + "\"");
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ public class PowerTestFixture{
|
|||||||
@BeforeAll
|
@BeforeAll
|
||||||
static void initializeDependencies(){
|
static void initializeDependencies(){
|
||||||
Core.graphics = new FakeGraphics();
|
Core.graphics = new FakeGraphics();
|
||||||
|
Vars.state = new GameState();
|
||||||
Vars.content = new ContentLoader(){
|
Vars.content = new ContentLoader(){
|
||||||
@Override
|
@Override
|
||||||
public void handleMappableContent(MappableContent content){
|
public void handleMappableContent(MappableContent content){
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package power;
|
|||||||
import arc.*;
|
import arc.*;
|
||||||
import arc.math.*;
|
import arc.math.*;
|
||||||
import arc.util.*;
|
import arc.util.*;
|
||||||
|
import mindustry.*;
|
||||||
|
import mindustry.core.*;
|
||||||
import mindustry.world.*;
|
import mindustry.world.*;
|
||||||
import mindustry.world.blocks.power.*;
|
import mindustry.world.blocks.power.*;
|
||||||
import mindustry.world.consumers.*;
|
import mindustry.world.consumers.*;
|
||||||
@@ -23,6 +25,7 @@ public class PowerTests extends PowerTestFixture{
|
|||||||
@BeforeAll
|
@BeforeAll
|
||||||
static void init(){
|
static void init(){
|
||||||
Core.graphics = new FakeGraphics();
|
Core.graphics = new FakeGraphics();
|
||||||
|
Vars.state = new GameState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
|
|||||||
@@ -240,7 +240,7 @@ task swapColors(){
|
|||||||
Color.argb8888ToColor(tmpc, c)
|
Color.argb8888ToColor(tmpc, c)
|
||||||
if(tmpc.a < 0.1f) continue
|
if(tmpc.a < 0.1f) continue
|
||||||
if(map.containsKey(c)){
|
if(map.containsKey(c)){
|
||||||
img.setRGB(x, y, (int) map.get(c))
|
img.setRGB(x, y, (int)map.get(c))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user