Many various internal changes
This commit is contained in:
@@ -61,10 +61,6 @@ public class Vars implements Loadable{
|
||||
public static final Array<String> defaultServers = Array.with();
|
||||
/** maximum distance between mine and core that supports automatic transferring */
|
||||
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 */
|
||||
public static final boolean enableUnitEditing = false;
|
||||
/** max chat message length */
|
||||
|
||||
@@ -103,7 +103,7 @@ public class BlockIndexer{
|
||||
}
|
||||
|
||||
private ObjectSet<Tile>[] getFlagged(Team team){
|
||||
return flagMap[(int) team.id];
|
||||
return flagMap[(int)team.id];
|
||||
}
|
||||
|
||||
/** @return whether this item is present on this map.*/
|
||||
@@ -115,11 +115,11 @@ public class BlockIndexer{
|
||||
public ObjectSet<Tile> getDamaged(Team team){
|
||||
returnArray.clear();
|
||||
|
||||
if(damagedTiles[(int) team.id] == null){
|
||||
damagedTiles[(int) team.id] = new ObjectSet<>();
|
||||
if(damagedTiles[(int)team.id] == null){
|
||||
damagedTiles[(int)team.id] = new ObjectSet<>();
|
||||
}
|
||||
|
||||
ObjectSet<Tile> set = damagedTiles[(int) team.id];
|
||||
ObjectSet<Tile> set = damagedTiles[(int)team.id];
|
||||
for(Tile tile : set){
|
||||
if((tile.entity == null || tile.entity.getTeam() != team || !tile.entity.damaged()) || tile.block() instanceof BuildBlock){
|
||||
returnArray.add(tile);
|
||||
@@ -135,7 +135,7 @@ public class BlockIndexer{
|
||||
|
||||
/** Get all allied blocks with a flag. */
|
||||
public ObjectSet<Tile> getAllied(Team team, BlockFlag type){
|
||||
return flagMap[(int) team.id][type.ordinal()];
|
||||
return flagMap[(int)team.id][type.ordinal()];
|
||||
}
|
||||
|
||||
/** Get all enemy blocks with a flag. */
|
||||
@@ -155,11 +155,11 @@ public class BlockIndexer{
|
||||
}
|
||||
|
||||
public void notifyTileDamaged(TileEntity entity){
|
||||
if(damagedTiles[(int) entity.getTeam().id] == null){
|
||||
damagedTiles[(int) entity.getTeam().id] = new ObjectSet<>();
|
||||
if(damagedTiles[(int)entity.getTeam().id] == null){
|
||||
damagedTiles[(int)entity.getTeam().id] = new ObjectSet<>();
|
||||
}
|
||||
|
||||
ObjectSet<Tile> set = damagedTiles[(int) entity.getTeam().id];
|
||||
ObjectSet<Tile> set = damagedTiles[(int)entity.getTeam().id];
|
||||
set.add(entity.tile);
|
||||
}
|
||||
|
||||
@@ -287,11 +287,11 @@ public class BlockIndexer{
|
||||
|
||||
//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){
|
||||
structQuadrants[(int) data.team.id].set(quadrantX, quadrantY);
|
||||
structQuadrants[(int)data.team.id].set(quadrantX, quadrantY);
|
||||
continue; //no need to process futher
|
||||
}
|
||||
|
||||
structQuadrants[(int) data.team.id].set(quadrantX, quadrantY, false);
|
||||
structQuadrants[(int)data.team.id].set(quadrantX, quadrantY, false);
|
||||
|
||||
outer:
|
||||
for(int x = quadrantX * quadrantSize; x < world.width() && x < (quadrantX + 1) * quadrantSize; x++){
|
||||
@@ -299,7 +299,7 @@ public class BlockIndexer{
|
||||
Tile result = world.ltile(x, y);
|
||||
//when a targetable block is found, mark this quadrant as occupied and stop searching
|
||||
if(result.entity != null && result.getTeam() == data.team){
|
||||
structQuadrants[(int) data.team.id].set(quadrantX, quadrantY);
|
||||
structQuadrants[(int)data.team.id].set(quadrantX, quadrantY);
|
||||
break outer;
|
||||
}
|
||||
}
|
||||
@@ -308,7 +308,7 @@ public class BlockIndexer{
|
||||
}
|
||||
|
||||
private boolean getQuad(Team team, int quadrantX, int quadrantY){
|
||||
return structQuadrants[(int) team.id].get(quadrantX, quadrantY);
|
||||
return structQuadrants[(int)team.id].get(quadrantX, quadrantY);
|
||||
}
|
||||
|
||||
private int quadWidth(){
|
||||
|
||||
@@ -53,7 +53,7 @@ public class Pathfinder implements Runnable{
|
||||
}
|
||||
|
||||
//special preset which may help speed things up; this is optional
|
||||
preloadPath(waveTeam, PathTarget.enemyCores);
|
||||
preloadPath(state.rules.waveTeam, PathTarget.enemyCores);
|
||||
|
||||
start();
|
||||
});
|
||||
@@ -84,8 +84,8 @@ public class Pathfinder implements Runnable{
|
||||
}
|
||||
|
||||
public int debugValue(Team team, int x, int y){
|
||||
if(pathMap[(int) team.id][PathTarget.enemyCores.ordinal()] == null) return 0;
|
||||
return pathMap[(int) team.id][PathTarget.enemyCores.ordinal()].weights[x][y];
|
||||
if(pathMap[(int)team.id][PathTarget.enemyCores.ordinal()] == null) return 0;
|
||||
return pathMap[(int)team.id][PathTarget.enemyCores.ordinal()].weights[x][y];
|
||||
}
|
||||
|
||||
/** 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){
|
||||
if(tile == null) return null;
|
||||
|
||||
PathData data = pathMap[(int) team.id][target.ordinal()];
|
||||
PathData data = pathMap[(int)team.id][target.ordinal()];
|
||||
|
||||
if(data == null){
|
||||
//if this combination is not found, create it on request
|
||||
if(!created.get((int) team.id, target.ordinal())){
|
||||
created.set((int) team.id, target.ordinal());
|
||||
if(!created.get((int)team.id, target.ordinal())){
|
||||
created.set((int)team.id, target.ordinal());
|
||||
//grab targets since this is run on main thread
|
||||
IntArray targets = target.getTargets(team, new IntArray());
|
||||
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.*/
|
||||
private boolean passable(int x, int y, Team team){
|
||||
int tile = tiles[x][y];
|
||||
return PathTile.passable(tile) || (PathTile.team(tile) != (int) team.id && PathTile.team(tile) != (int) Team.derelict.id);
|
||||
return PathTile.passable(tile) || (PathTile.team(tile) != (int)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());
|
||||
|
||||
list.add(path);
|
||||
pathMap[(int) team.id][target.ordinal()] = path;
|
||||
pathMap[(int)team.id][target.ordinal()] = path;
|
||||
|
||||
//grab targets from passed array
|
||||
synchronized(path.targets){
|
||||
@@ -303,7 +303,7 @@ public class Pathfinder implements Runnable{
|
||||
}
|
||||
|
||||
//spawn points are also enemies.
|
||||
if(state.rules.waves && team == defaultTeam){
|
||||
if(state.rules.waves && team == state.rules.defaultTeam){
|
||||
for(Tile other : spawner.getGroundSpawns()){
|
||||
out.add(other.pos());
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ public class WaveSpawner{
|
||||
|
||||
eachFlyerSpawn((spawnX, spawnY) -> {
|
||||
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.add();
|
||||
}
|
||||
@@ -66,7 +66,7 @@ public class WaveSpawner{
|
||||
for(int i = 0; i < spawned; i++){
|
||||
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);
|
||||
|
||||
Time.run(Math.min(i * 5, 60 * 2), () -> spawnEffect(unit));
|
||||
@@ -78,7 +78,7 @@ public class WaveSpawner{
|
||||
eachGroundSpawn((spawnX, spawnY, doShockwave) -> {
|
||||
if(doShockwave){
|
||||
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,9 +90,9 @@ public class WaveSpawner{
|
||||
cons.accept(spawn.worldx(), spawn.worldy(), true);
|
||||
}
|
||||
|
||||
if(state.rules.attackMode && state.teams.isActive(waveTeam) && !state.teams.get(defaultTeam).cores.isEmpty()){
|
||||
Tile firstCore = state.teams.get(defaultTeam).cores.first();
|
||||
for(Tile core : state.teams.get(waveTeam).cores){
|
||||
if(state.rules.attackMode && state.teams.isActive(state.rules.waveTeam) && !state.teams.playerCores().isEmpty()){
|
||||
Tile firstCore = state.teams.playerCores().first();
|
||||
for(Tile core : state.teams.get(state.rules.waveTeam).cores){
|
||||
Tmp.v1.set(firstCore).sub(core.worldx(), core.worldy()).limit(coreMargin + core.block().size*tilesize);
|
||||
cons.accept(core.worldx() + Tmp.v1.x, core.worldy() + Tmp.v1.y, false);
|
||||
}
|
||||
@@ -107,8 +107,8 @@ public class WaveSpawner{
|
||||
cons.get(spawnX, spawnY);
|
||||
}
|
||||
|
||||
if(state.rules.attackMode && state.teams.isActive(waveTeam)){
|
||||
for(Tile core : state.teams.get(waveTeam).cores){
|
||||
if(state.rules.attackMode && state.teams.isActive(state.rules.waveTeam)){
|
||||
for(Tile core : state.teams.get(state.rules.waveTeam).cores){
|
||||
cons.get(core.worldx(), core.worldy());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,7 @@ import mindustry.entities.Effects;
|
||||
import mindustry.ctype.ContentList;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.type.StatusEffect;
|
||||
|
||||
import static mindustry.Vars.waveTeam;
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class StatusEffects implements ContentList{
|
||||
public static StatusEffect none, burning, freezing, wet, melting, tarred, overdrive, shielded, shocked, corroded, boss;
|
||||
@@ -48,7 +47,7 @@ public class StatusEffects implements ContentList{
|
||||
init(() -> {
|
||||
trans(shocked, ((unit, time, newTime, result) -> {
|
||||
unit.damage(20f);
|
||||
if(unit.getTeam() == waveTeam){
|
||||
if(unit.getTeam() == state.rules.waveTeam){
|
||||
Events.fire(Trigger.shock);
|
||||
}
|
||||
result.set(this, time);
|
||||
|
||||
@@ -63,7 +63,7 @@ public class Control implements ApplicationListener, Loadable{
|
||||
});
|
||||
|
||||
Events.on(PlayEvent.class, event -> {
|
||||
player.setTeam(state.rules.pvp ? netServer.assignTeam(player, playerGroup.all()) : defaultTeam);
|
||||
player.setTeam(state.rules.pvp ? netServer.assignTeam(player, playerGroup.all()) : state.rules.defaultTeam);
|
||||
player.setDead(true);
|
||||
player.add();
|
||||
|
||||
@@ -256,9 +256,9 @@ public class Control implements ApplicationListener, Loadable{
|
||||
world.loadGenerator(zone.generator);
|
||||
zone.rules.get(state.rules);
|
||||
state.rules.zone = zone;
|
||||
for(Tile core : state.teams.get(defaultTeam).cores){
|
||||
for(TileEntity core : state.teams.playerCores()){
|
||||
for(ItemStack stack : zone.getStartingItems()){
|
||||
core.entity.items.add(stack.item, stack.amount);
|
||||
core.items.add(stack.item, stack.amount);
|
||||
}
|
||||
}
|
||||
state.set(State.playing);
|
||||
@@ -294,8 +294,8 @@ public class Control implements ApplicationListener, Loadable{
|
||||
|
||||
Geometry.circle(coreb.x, coreb.y, 10, (cx, cy) -> {
|
||||
Tile tile = world.ltile(cx, cy);
|
||||
if(tile != null && tile.getTeam() == defaultTeam && !(tile.block() instanceof CoreBlock)){
|
||||
world.removeBlock(tile);
|
||||
if(tile != null && tile.getTeam() == state.rules.defaultTeam && !(tile.block() instanceof CoreBlock)){
|
||||
tile.remove();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -305,13 +305,13 @@ public class Control implements ApplicationListener, Loadable{
|
||||
|
||||
zone.rules.get(state.rules);
|
||||
state.rules.zone = zone;
|
||||
for(Tile core : state.teams.get(defaultTeam).cores){
|
||||
for(TileEntity core : state.teams.playerCores()){
|
||||
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();
|
||||
core.entity.items.clear();
|
||||
TileEntity core = state.teams.playerCores().first();
|
||||
core.items.clear();
|
||||
|
||||
logic.play();
|
||||
state.rules.waveTimer = false;
|
||||
@@ -434,9 +434,9 @@ public class Control implements ApplicationListener, Loadable{
|
||||
input.update();
|
||||
|
||||
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()){
|
||||
if(tile.entity != null && tile.entity.items.has(item)){
|
||||
if(tile.items.has(item)){
|
||||
data.unlockContent(item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ public class GameState{
|
||||
private State state = State.menu;
|
||||
|
||||
public BaseUnit boss(){
|
||||
return unitGroup.find(u -> u.isBoss() && u.getTeam() == waveTeam);
|
||||
return unitGroup.find(u -> u.isBoss() && u.getTeam() == rules.waveTeam);
|
||||
}
|
||||
|
||||
public void set(State astate){
|
||||
|
||||
@@ -107,9 +107,9 @@ public class Logic implements ApplicationListener{
|
||||
|
||||
//add starting items
|
||||
if(!world.isZone()){
|
||||
for(Team team : Team.all){
|
||||
if(!state.teams.get(team).cores.isEmpty()){
|
||||
TileEntity entity = state.teams.get(team).cores.first().entity;
|
||||
for(TeamData team : state.teams.getActive()){
|
||||
if(team.hasCore()){
|
||||
TileEntity entity = team.core();
|
||||
entity.items.clear();
|
||||
for(ItemStack stack : state.rules.loadout){
|
||||
entity.items.add(stack.item, stack.amount);
|
||||
@@ -143,23 +143,23 @@ public class Logic implements ApplicationListener{
|
||||
}
|
||||
|
||||
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;
|
||||
Events.fire(new GameOverEvent(waveTeam));
|
||||
Events.fire(new GameOverEvent(state.rules.waveTeam));
|
||||
}else if(state.rules.attackMode){
|
||||
Team alive = null;
|
||||
|
||||
for(Team team : Team.all){
|
||||
if(state.teams.get(team).cores.size > 0){
|
||||
for(TeamData team : state.teams.getActive()){
|
||||
if(team.hasCore()){
|
||||
if(alive != null){
|
||||
return;
|
||||
}
|
||||
alive = team;
|
||||
alive = team.team;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
Call.launchZone();
|
||||
}else{
|
||||
@@ -176,7 +176,7 @@ public class Logic implements ApplicationListener{
|
||||
ui.hudfrag.showLaunch();
|
||||
}
|
||||
|
||||
for(Tile tile : state.teams.get(defaultTeam).cores){
|
||||
for(TileEntity tile : state.teams.playerCores()){
|
||||
Effects.effect(Fx.launch, tile);
|
||||
}
|
||||
|
||||
@@ -185,19 +185,18 @@ public class Logic implements ApplicationListener{
|
||||
}
|
||||
|
||||
Time.runTask(30f, () -> {
|
||||
for(Tile tile : state.teams.get(defaultTeam).cores){
|
||||
for(TileEntity entity : state.teams.playerCores()){
|
||||
for(Item item : content.items()){
|
||||
if(tile == null || tile.entity == null || tile.entity.items == null) continue;
|
||||
data.addItem(item, tile.entity.items.get(item));
|
||||
Events.fire(new LaunchItemEvent(item, tile.entity.items.get(item)));
|
||||
data.addItem(item, entity.items.get(item));
|
||||
Events.fire(new LaunchItemEvent(item, entity.items.get(item)));
|
||||
}
|
||||
world.removeBlock(tile);
|
||||
entity.tile.remove();
|
||||
}
|
||||
state.launched = true;
|
||||
state.gameOver = true;
|
||||
Events.fire(new LaunchEvent());
|
||||
//manually fire game over event now
|
||||
Events.fire(new GameOverEvent(defaultTeam));
|
||||
Events.fire(new GameOverEvent(state.rules.defaultTeam));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -213,7 +212,7 @@ public class Logic implements ApplicationListener{
|
||||
|
||||
if(!state.is(State.menu)){
|
||||
if(!net.client()){
|
||||
state.enemies = unitGroup.count(b -> b.getTeam() == waveTeam && b.countsAsEnemy());
|
||||
state.enemies = unitGroup.count(b -> b.getTeam() == state.rules.waveTeam && b.countsAsEnemy());
|
||||
}
|
||||
|
||||
if(!state.isPaused()){
|
||||
|
||||
@@ -17,11 +17,13 @@ import mindustry.entities.traits.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.game.Teams.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.net.*;
|
||||
import mindustry.net.Administration.*;
|
||||
import mindustry.net.Packets.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.storage.CoreBlock.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.*;
|
||||
@@ -402,18 +404,16 @@ public class NetServer implements ApplicationListener{
|
||||
|
||||
public Team assignTeam(Player current, Iterable<Player> players){
|
||||
//find team with minimum amount of players and auto-assign player to that.
|
||||
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++;
|
||||
}
|
||||
TeamData re = state.teams.getActive().min(data -> {
|
||||
int count = 0;
|
||||
for(Player other : players){
|
||||
if(other.getTeam() == data.team && other != current){
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
return Integer.MAX_VALUE;
|
||||
return count;
|
||||
});
|
||||
return re == null ? null : re.team;
|
||||
}
|
||||
|
||||
public void sendWorldData(Player player){
|
||||
@@ -584,8 +584,8 @@ public class NetServer implements ApplicationListener{
|
||||
public boolean isWaitingForPlayers(){
|
||||
if(state.rules.pvp){
|
||||
int used = 0;
|
||||
for(Team t : Team.all){
|
||||
if(playerGroup.count(p -> p.getTeam() == t) > 0){
|
||||
for(TeamData t : state.teams.getActive()){
|
||||
if(playerGroup.count(p -> p.getTeam() == t.team) > 0){
|
||||
used++;
|
||||
}
|
||||
}
|
||||
@@ -647,13 +647,13 @@ public class NetServer implements ApplicationListener{
|
||||
|
||||
public void writeEntitySnapshot(Player player) throws IOException{
|
||||
syncStream.reset();
|
||||
ObjectSet<Tile> cores = state.teams.get(player.getTeam()).cores;
|
||||
Array<CoreEntity> cores = state.teams.cores(player.getTeam());
|
||||
|
||||
dataStream.writeByte(cores.size);
|
||||
|
||||
for(Tile tile : cores){
|
||||
dataStream.writeInt(tile.pos());
|
||||
tile.entity.items.write(dataStream);
|
||||
for(CoreEntity entity : cores){
|
||||
dataStream.writeInt(entity.tile.pos());
|
||||
entity.items.write(dataStream);
|
||||
}
|
||||
|
||||
dataStream.close();
|
||||
|
||||
@@ -18,11 +18,10 @@ import mindustry.entities.effect.*;
|
||||
import mindustry.entities.effect.GroundEffectEntity.*;
|
||||
import mindustry.entities.traits.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.input.*;
|
||||
import mindustry.ui.Cicon;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.world.blocks.defense.ForceProjector.*;
|
||||
|
||||
import static arc.Core.*;
|
||||
@@ -344,11 +343,7 @@ public class Renderer implements ApplicationListener{
|
||||
Draw.rect("circle-shadow", u.x, u.y, size * rad, size * rad);
|
||||
};
|
||||
|
||||
for(EntityGroup<? extends BaseUnit> group : unitGroups){
|
||||
if(!group.isEmpty()){
|
||||
group.draw(unit -> !unit.isDead(), draw::get);
|
||||
}
|
||||
}
|
||||
unitGroup.draw(unit -> !unit.isDead(), draw::get);
|
||||
|
||||
if(!playerGroup.isEmpty()){
|
||||
playerGroup.draw(unit -> !unit.isDead(), draw::get);
|
||||
@@ -361,34 +356,21 @@ public class Renderer implements ApplicationListener{
|
||||
float trnsX = -12, trnsY = -13;
|
||||
Draw.color(0, 0, 0, 0.22f);
|
||||
|
||||
for(EntityGroup<? extends BaseUnit> group : unitGroups){
|
||||
if(!group.isEmpty()){
|
||||
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));
|
||||
}
|
||||
unitGroup.draw(unit -> unit.isFlying() && !unit.isDead(), baseUnit -> baseUnit.drawShadow(trnsX, trnsY));
|
||||
playerGroup.draw(unit -> unit.isFlying() && !unit.isDead(), player -> player.drawShadow(trnsX, trnsY));
|
||||
|
||||
Draw.color();
|
||||
}
|
||||
|
||||
private void drawAllTeams(boolean flying){
|
||||
for(Team team : Team.all){
|
||||
EntityGroup<BaseUnit> group = unitGroups[(int) team.id];
|
||||
unitGroup.draw(u -> u.isFlying() == flying && !u.isDead(), Unit::drawUnder);
|
||||
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[(int) team.id].draw(u -> u.isFlying() == flying && !u.isDead(), Unit::drawUnder);
|
||||
playerGroup.draw(p -> p.isFlying() == flying && p.getTeam() == team && !p.isDead(), Unit::drawUnder);
|
||||
|
||||
unitGroups[(int) team.id].draw(u -> u.isFlying() == flying && !u.isDead(), Unit::drawAll);
|
||||
playerGroup.draw(p -> p.isFlying() == flying && p.getTeam() == team, Unit::drawAll);
|
||||
|
||||
unitGroups[(int) team.id].draw(u -> u.isFlying() == flying && !u.isDead(), Unit::drawOver);
|
||||
playerGroup.draw(p -> p.isFlying() == flying && p.getTeam() == team, Unit::drawOver);
|
||||
}
|
||||
unitGroup.draw(u -> u.isFlying() == flying && !u.isDead(), Unit::drawOver);
|
||||
playerGroup.draw(p -> p.isFlying() == flying, Unit::drawOver);
|
||||
}
|
||||
|
||||
public void scaleCamera(float amount){
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
package mindustry.core;
|
||||
|
||||
import arc.*;
|
||||
import arc.struct.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.util.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import mindustry.content.*;
|
||||
import arc.util.*;
|
||||
import mindustry.core.GameState.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.game.Teams.*;
|
||||
import mindustry.io.*;
|
||||
import mindustry.maps.*;
|
||||
import mindustry.maps.filters.*;
|
||||
@@ -233,33 +233,22 @@ public class World{
|
||||
invalidMap = false;
|
||||
|
||||
if(!headless){
|
||||
if(state.teams.get(defaultTeam).cores.size == 0 && !checkRules.pvp){
|
||||
if(state.teams.playerCores().size == 0 && !checkRules.pvp){
|
||||
ui.showErrorMessage("$map.nospawn");
|
||||
invalidMap = true;
|
||||
}else if(checkRules.pvp){ //pvp maps need two cores to be valid
|
||||
int teams = 0;
|
||||
for(Team team : Team.all){
|
||||
if(state.teams.get(team).cores.size != 0){
|
||||
teams ++;
|
||||
}
|
||||
}
|
||||
if(teams < 2){
|
||||
if(state.teams.getActive().count(TeamData::hasCore) < 2){
|
||||
invalidMap = true;
|
||||
ui.showErrorMessage("$map.nospawn.pvp");
|
||||
}
|
||||
}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){
|
||||
ui.showErrorMessage("$map.nospawn.attack");
|
||||
}
|
||||
}
|
||||
}else{
|
||||
invalidMap = true;
|
||||
for(Team team : Team.all){
|
||||
if(state.teams.get(team).cores.size != 0){
|
||||
invalidMap = false;
|
||||
}
|
||||
}
|
||||
invalidMap = !state.teams.getActive().contains(TeamData::hasCore);
|
||||
|
||||
if(invalidMap){
|
||||
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){
|
||||
raycastEach(toTile(x0), toTile(y0), toTile(x1), toTile(y1), cons);
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ public class DrawOperation{
|
||||
}else if(type == OpType.rotation.ordinal()){
|
||||
tile.rotation(to);
|
||||
}else if(type == OpType.team.ordinal()){
|
||||
tile.setTeam(Team.all[to]);
|
||||
tile.setTeam(Team.get(to));
|
||||
}else if(type == OpType.overlay.ordinal()){
|
||||
tile.setOverlayID(to);
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ public class EditorTile extends Tile{
|
||||
return;
|
||||
}
|
||||
|
||||
if(getTeamID() == (int) team.id) return;
|
||||
if(getTeamID() == (int)team.id) return;
|
||||
op(OpType.team, getTeamID());
|
||||
super.setTeam(team);
|
||||
}
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
package mindustry.editor;
|
||||
|
||||
import arc.struct.IntArray;
|
||||
import arc.func.*;
|
||||
import arc.math.Mathf;
|
||||
import arc.math.geom.Bresenham2;
|
||||
import arc.util.Structs;
|
||||
import mindustry.Vars;
|
||||
import mindustry.content.Blocks;
|
||||
import mindustry.game.Team;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.BlockPart;
|
||||
import mindustry.world.blocks.*;
|
||||
|
||||
public enum EditorTool{
|
||||
zoom,
|
||||
@@ -80,7 +79,7 @@ public enum EditorTool{
|
||||
editor.drawCircle(x, y, tile -> {
|
||||
if(mode == -1){
|
||||
//erase block
|
||||
Vars.world.removeBlock(tile);
|
||||
tile.remove();
|
||||
}else if(mode == 0){
|
||||
//erase ore
|
||||
tile.clearOverlay();
|
||||
@@ -141,7 +140,7 @@ public enum EditorTool{
|
||||
if(tile.link().synthetic()){
|
||||
Team dest = tile.getTeam();
|
||||
if(dest == editor.drawTeam) return;
|
||||
fill(editor, x, y, false, t -> t.getTeamID() == (int) dest.id && 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.game.Team;
|
||||
import mindustry.gen.TileOp;
|
||||
import mindustry.io.LegacyMapIO;
|
||||
import mindustry.io.MapIO;
|
||||
import mindustry.maps.Map;
|
||||
import mindustry.world.*;
|
||||
@@ -65,7 +64,7 @@ public class MapEditor{
|
||||
reset();
|
||||
|
||||
createTiles(pixmap.getWidth(), pixmap.getHeight());
|
||||
load(() -> LegacyMapIO.readPixmap(pixmap, tiles()));
|
||||
load(() -> MapIO.readPixmap(pixmap, tiles()));
|
||||
renderer.resize(width(), height());
|
||||
}
|
||||
|
||||
@@ -86,7 +85,7 @@ public class MapEditor{
|
||||
for(int x = 0; x < width(); x++){
|
||||
for(int y = 0; y < height(); y++){
|
||||
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{
|
||||
boolean isFloor = drawBlock.isFloor() && drawBlock != Blocks.air;
|
||||
|
||||
@@ -185,7 +184,7 @@ public class MapEditor{
|
||||
|
||||
//remove linked tiles blocking the way
|
||||
if(!isFloor && (tile.isLinked() || tile.block().isMultiblock())){
|
||||
world.removeBlock(tile.link());
|
||||
tile.link().remove();
|
||||
}
|
||||
|
||||
if(isFloor){
|
||||
|
||||
@@ -551,7 +551,7 @@ public class MapEditorDialog extends Dialog implements Disposable{
|
||||
|
||||
int i = 0;
|
||||
|
||||
for(Team team : Team.all){
|
||||
for(Team team : Team.base()){
|
||||
ImageButton button = new ImageButton(Tex.whiteui, Styles.clearTogglePartiali);
|
||||
button.margin(4f);
|
||||
button.getImageCell().grow();
|
||||
|
||||
@@ -138,7 +138,7 @@ public class MapGenerateDialog extends FloatingDialog{
|
||||
tile.rotation(write.rotation);
|
||||
tile.setFloor((Floor)content.block(write.floor));
|
||||
tile.setBlock(content.block(write.block));
|
||||
tile.setTeam(Team.all[write.team]);
|
||||
tile.setTeam(Team.get(write.team));
|
||||
tile.setOverlay(content.block(write.ore));
|
||||
}
|
||||
}
|
||||
@@ -367,7 +367,7 @@ public class MapGenerateDialog extends FloatingDialog{
|
||||
GenTile tile = buffer1[px][py];
|
||||
input.apply(x, y, content.block(tile.floor), content.block(tile.block), content.block(tile.ore));
|
||||
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++){
|
||||
@@ -415,7 +415,7 @@ public class MapGenerateDialog extends FloatingDialog{
|
||||
this.floor = floor.id;
|
||||
this.block = wall.id;
|
||||
this.ore = ore.id;
|
||||
this.team = (byte) (int) team.id;
|
||||
this.team = (byte) (int)team.id;
|
||||
this.rotation = (byte)rotation;
|
||||
}
|
||||
|
||||
@@ -437,7 +437,7 @@ public class MapGenerateDialog extends FloatingDialog{
|
||||
ctile.setBlock(content.block(block));
|
||||
ctile.setOverlay(content.block(ore));
|
||||
ctile.rotation(rotation);
|
||||
ctile.setTeam(Team.all[team]);
|
||||
ctile.setTeam(Team.get(team));
|
||||
return ctile;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ public class Damage{
|
||||
tr.trns(angle, length);
|
||||
Intc2 collider = (cx, cy) -> {
|
||||
Tile tile = world.ltile(cx, cy);
|
||||
if(tile != null && !collidedBlocks.contains(tile.pos()) && tile.entity != null && tile.getTeamID() != (int) team.id && tile.entity.collide(hitter)){
|
||||
if(tile != null && !collidedBlocks.contains(tile.pos()) && tile.entity != null && tile.getTeamID() != (int)team.id && tile.entity.collide(hitter)){
|
||||
tile.entity.collision(hitter);
|
||||
collidedBlocks.add(tile.pos());
|
||||
hitter.getBulletType().hit(hitter, tile.worldx(), tile.worldy());
|
||||
|
||||
@@ -157,7 +157,7 @@ public class Units{
|
||||
|
||||
/** Iterates over all units in a rectangle. */
|
||||
public static void nearby(Team team, float x, float y, float width, float height, Cons<Unit> cons){
|
||||
unitGroups[(int) team.id].intersect(x, y, width, height, cons);
|
||||
unitGroups[(int)team.id].intersect(x, y, width, height, cons);
|
||||
playerGroup.intersect(x, y, width, height, player -> {
|
||||
if(player.getTeam() == team){
|
||||
cons.get(player);
|
||||
@@ -167,7 +167,7 @@ public class Units{
|
||||
|
||||
/** 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){
|
||||
unitGroups[(int) team.id].intersect(x - radius, y - radius, radius*2f, radius*2f, unit -> {
|
||||
unitGroups[(int)team.id].intersect(x - radius, y - radius, radius*2f, radius*2f, unit -> {
|
||||
if(unit.withinDst(x, y, radius)){
|
||||
cons.get(unit);
|
||||
}
|
||||
@@ -183,7 +183,7 @@ public class Units{
|
||||
/** Iterates over all units in a rectangle. */
|
||||
public static void nearby(float x, float y, float width, float height, Cons<Unit> cons){
|
||||
for(Team team : Team.all){
|
||||
unitGroups[(int) team.id].intersect(x, y, width, height, cons);
|
||||
unitGroups[(int)team.id].intersect(x, y, width, height, cons);
|
||||
}
|
||||
|
||||
playerGroup.intersect(x, y, width, height, cons);
|
||||
@@ -199,7 +199,7 @@ public class Units{
|
||||
EnumSet<Team> targets = state.teams.enemiesOf(team);
|
||||
|
||||
for(Team other : targets){
|
||||
unitGroups[(int) other.id].intersect(x, y, width, height, cons);
|
||||
unitGroups[(int)other.id].intersect(x, y, width, height, cons);
|
||||
}
|
||||
|
||||
playerGroup.intersect(x, y, width, height, player -> {
|
||||
@@ -216,10 +216,7 @@ public class Units{
|
||||
|
||||
/** Iterates over all units. */
|
||||
public static void all(Cons<Unit> cons){
|
||||
for(Team team : Team.all){
|
||||
unitGroups[(int) team.id].all().each(cons);
|
||||
}
|
||||
|
||||
unitGroup.all().each(cons);
|
||||
playerGroup.all().each(cons);
|
||||
}
|
||||
|
||||
|
||||
@@ -185,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));
|
||||
}
|
||||
|
||||
public Tile getClosestSpawner(){
|
||||
public @Nullable Tile getClosestSpawner(){
|
||||
return Geometry.findClosest(x, y, Vars.spawner.getGroundSpawns());
|
||||
}
|
||||
|
||||
public TileEntity getClosestEnemyCore(){
|
||||
for(Team enemy : Vars.state.teams.enemiesOf(team)){
|
||||
Tile tile = Geometry.findClosest(x, y, Vars.state.teams.get(enemy).cores);
|
||||
if(tile != null){
|
||||
return tile.entity;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
public @Nullable TileEntity getClosestEnemyCore(){
|
||||
return Vars.state.teams.closestEnemyCore(x, y, team);
|
||||
}
|
||||
|
||||
public UnitState getStartState(){
|
||||
@@ -370,7 +363,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{
|
||||
|
||||
@Override
|
||||
public EntityGroup targetGroup(){
|
||||
return unitGroups[(int) team.id];
|
||||
return unitGroup;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -124,7 +124,8 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{
|
||||
@CallSuper
|
||||
public void write(DataOutput stream) throws IOException{
|
||||
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(power != null) power.write(stream);
|
||||
if(liquids != null) liquids.write(stream);
|
||||
@@ -134,11 +135,11 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{
|
||||
@CallSuper
|
||||
public void read(DataInput stream, byte revision) throws IOException{
|
||||
health = stream.readUnsignedShort();
|
||||
byte tr = stream.readByte();
|
||||
byte team = Pack.leftByte(tr);
|
||||
byte rotation = Pack.rightByte(tr);
|
||||
byte packedrot = stream.readByte();
|
||||
byte team = Pack.leftByte(packedrot) == 8 ? stream.readByte() : Pack.leftByte(packedrot);
|
||||
byte rotation = Pack.rightByte(packedrot);
|
||||
|
||||
tile.setTeam(Team.all[team]);
|
||||
tile.setTeam(Team.get(team));
|
||||
tile.rotation(rotation);
|
||||
|
||||
if(items != null) items.read(stream);
|
||||
@@ -277,7 +278,7 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{
|
||||
Events.fire(new BlockDestroyEvent(tile));
|
||||
block.breakSound.at(tile);
|
||||
block.onDestroyed(tile);
|
||||
world.removeBlock(tile);
|
||||
tile.remove();
|
||||
remove();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package mindustry.entities.type;
|
||||
|
||||
import arc.*;
|
||||
import arc.struct.*;
|
||||
import arc.graphics.*;
|
||||
import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import mindustry.content.*;
|
||||
@@ -16,13 +16,11 @@ import mindustry.entities.traits.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.game.Teams.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.net.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.ui.Cicon;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.*;
|
||||
|
||||
@@ -158,7 +156,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
||||
this.item.amount = itemAmount;
|
||||
this.item.item = content.item(itemID);
|
||||
this.dead = dead;
|
||||
this.team = Team.all[team];
|
||||
this.team = Team.get(team);
|
||||
this.health = health;
|
||||
this.x = x;
|
||||
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{
|
||||
if(item.item == null) item.item = Items.copper;
|
||||
|
||||
stream.writeByte((int) team.id);
|
||||
stream.writeByte((int)team.id);
|
||||
stream.writeBoolean(isDead());
|
||||
stream.writeFloat(net ? interpolator.target.x : x);
|
||||
stream.writeFloat(net ? interpolator.target.y : y);
|
||||
@@ -217,13 +215,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
||||
float fsize = getSize() / radScl;
|
||||
moveVector.setZero();
|
||||
float cx = x - fsize/2f, cy = y - fsize/2f;
|
||||
|
||||
for(Team team : Team.all){
|
||||
if(team != getTeam() || !(this instanceof Player)){
|
||||
avoid(unitGroups[(int) team.id].intersect(cx, cy, fsize, fsize));
|
||||
}
|
||||
}
|
||||
|
||||
avoid(unitGroup.intersect(cx, cy, fsize, fsize));
|
||||
if(!(this instanceof Player)){
|
||||
avoid(playerGroup.intersect(cx, cy, fsize, fsize));
|
||||
}
|
||||
@@ -242,14 +234,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
||||
}
|
||||
|
||||
public @Nullable TileEntity getClosestCore(){
|
||||
TeamData data = state.teams.get(team);
|
||||
|
||||
Tile tile = Geometry.findClosest(x, y, data.cores);
|
||||
if(tile == null){
|
||||
return null;
|
||||
}else{
|
||||
return tile.entity;
|
||||
}
|
||||
return state.teams.closestCore(x, y, team);
|
||||
}
|
||||
|
||||
public Floor getFloorOn(){
|
||||
@@ -275,7 +260,7 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ
|
||||
}
|
||||
|
||||
//apply knockback based on spawns
|
||||
if(getTeam() != waveTeam){
|
||||
if(getTeam() != state.rules.waveTeam){
|
||||
float relativeSize = state.rules.dropZoneRadius + getSize()/2f + 1f;
|
||||
for(Tile spawn : spawner.getGroundSpawns()){
|
||||
if(withinDst(spawn.worldx(), spawn.worldy(), relativeSize)){
|
||||
|
||||
@@ -114,7 +114,7 @@ public class BuilderDrone extends BaseDrone implements BuilderTrait{
|
||||
public BuilderDrone(){
|
||||
if(reset.check()){
|
||||
Events.on(BuildSelectEvent.class, event -> {
|
||||
EntityGroup<BaseUnit> group = unitGroups[(int) event.team.id];
|
||||
EntityGroup<BaseUnit> group = unitGroups[(int)event.team.id];
|
||||
|
||||
if(!(event.tile.entity instanceof BuildEntity)) return;
|
||||
|
||||
|
||||
@@ -7,13 +7,14 @@ import mindustry.entities.type.BaseUnit;
|
||||
import mindustry.entities.type.TileEntity;
|
||||
import mindustry.gen.Call;
|
||||
import mindustry.type.Item;
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public class UnitDrops{
|
||||
private static Item[] dropTable;
|
||||
|
||||
public static void dropItems(BaseUnit unit){
|
||||
//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;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ import arc.*;
|
||||
import arc.func.*;
|
||||
import mindustry.maps.*;
|
||||
|
||||
import static mindustry.Vars.waveTeam;
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
/** Defines preset rule sets. */
|
||||
public enum Gamemode{
|
||||
@@ -22,7 +22,7 @@ public enum Gamemode{
|
||||
attack(rules -> {
|
||||
rules.unitDrops = true;
|
||||
rules.attackMode = true;
|
||||
}, map -> map.teams.contains((int) waveTeam.id)),
|
||||
}, map -> map.teams.contains((int)state.rules.waveTeam.id)),
|
||||
pvp(rules -> {
|
||||
rules.pvp = true;
|
||||
rules.enemyCoreBuildRadius = 600f;
|
||||
|
||||
@@ -83,7 +83,7 @@ public class MusicControl{
|
||||
|
||||
/** Whether to play dark music.*/
|
||||
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
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -78,6 +78,10 @@ public class Rules{
|
||||
public boolean lighting = false;
|
||||
/** Ambient light color, used when lighting is enabled. */
|
||||
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;
|
||||
|
||||
/** Copies this ruleset exactly. Not very efficient at all, do not use often. */
|
||||
public Rules copy(){
|
||||
|
||||
@@ -254,7 +254,7 @@ public class Schematics implements Loadable{
|
||||
Tile tile = world.tile(st.x + ox, st.y + oy);
|
||||
if(tile == null) return;
|
||||
|
||||
world.setBlock(tile, st.block, defaultTeam);
|
||||
tile.set(st.block, state.rules.defaultTeam);
|
||||
tile.rotation(st.rotation);
|
||||
if(st.block.posConfig){
|
||||
tile.configureAny(Pos.get(tile.x - st.x + Pos.x(st.config), tile.y - st.y + Pos.y(st.config)));
|
||||
|
||||
@@ -2,34 +2,66 @@ package mindustry.game;
|
||||
|
||||
import arc.*;
|
||||
import arc.graphics.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.graphics.*;
|
||||
|
||||
public class Team{
|
||||
/** All registered teams. */
|
||||
public final static Array<Team> all = new Array<>();
|
||||
public final static Team
|
||||
derelict = new Team("derelict", Color.valueOf("4d4e58")),
|
||||
sharded = new Team("sharded", Pal.accent.cpy()),
|
||||
crux = new Team("crux", Color.valueOf("e82d2d")),
|
||||
green = new Team("green", Color.valueOf("4dd98b")),
|
||||
purple = new Team("purple", Color.valueOf("9a4bdf")),
|
||||
blue = new Team("blue", Color.royal.cpy());
|
||||
|
||||
public class Team implements Comparable<Team>{
|
||||
public final Color color;
|
||||
public final int intColor;
|
||||
public final String name;
|
||||
public final int id;
|
||||
public final byte id;
|
||||
|
||||
public Team(String name, 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{
|
||||
//create the whole 256 placeholder teams
|
||||
for(int i = 6; i < all.length; i++){
|
||||
new Team(i, "team#" + i, Color.HSVtoRGB(360f * (float)(i) / all.length, 100f, 100f, 1f));
|
||||
}
|
||||
}
|
||||
|
||||
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.intColor = Color.rgba8888(color);
|
||||
this.id = all.size;
|
||||
all.add(this);
|
||||
this.id = (byte)id;
|
||||
|
||||
int us = Pack.u(this.id);
|
||||
if(us < 6) baseTeams[us] = this;
|
||||
all[us] = this;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,44 +1,82 @@
|
||||
package mindustry.game;
|
||||
|
||||
import arc.func.*;
|
||||
import arc.math.geom.*;
|
||||
import arc.struct.*;
|
||||
import mindustry.*;
|
||||
import arc.util.*;
|
||||
import arc.util.ArcAnnotate.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.storage.CoreBlock.*;
|
||||
|
||||
import static mindustry.Vars.state;
|
||||
|
||||
/** Class for various team-based utilities. */
|
||||
public class Teams{
|
||||
/** Maps team IDs to team data. */
|
||||
private Array<TeamData> map = new Array<>();
|
||||
private TeamData[] map = new TeamData[256];
|
||||
/** Active teams. */
|
||||
private Array<TeamData> active = new Array<>();
|
||||
|
||||
public <T> T eachEnemyCore(Team team, Func<TileEntity, T> ret){
|
||||
T out = null;
|
||||
//todo each enemy, each enemy core...
|
||||
return out;
|
||||
public @Nullable CoreEntity closestEnemyCore(float x, float y, Team team){
|
||||
for(TeamData data : active){
|
||||
if(areEnemies(team, data.team)){
|
||||
CoreEntity tile = Geometry.findClosest(x, y, data.cores);
|
||||
if(tile != null){
|
||||
return tile;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a team.
|
||||
* @param team The team type enum.
|
||||
*/
|
||||
public void add(Team team){
|
||||
map[team.id] = new TeamData(team);
|
||||
public @Nullable CoreEntity closestCore(float x, float y, Team team){
|
||||
return Geometry.findClosest(x, y, get(team).cores);
|
||||
}
|
||||
|
||||
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. */
|
||||
public TeamData get(Team team){
|
||||
if(map[team.id] == null){
|
||||
add(team);
|
||||
if(map[Pack.u(team.id)] == null){
|
||||
map[Pack.u(team.id)] = new TeamData(team);
|
||||
}
|
||||
return map[team.id];
|
||||
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. */
|
||||
public boolean isActive(Team team){
|
||||
//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 whether {@param other} is an enemy of {@param #team}. */
|
||||
@@ -47,20 +85,63 @@ public class Teams{
|
||||
return team != other;
|
||||
}
|
||||
|
||||
/** Allocates a new array with the active teams.
|
||||
* Never call in the main game loop.*/
|
||||
public Array<TeamData> getActive(){
|
||||
return Array.select(map, t -> t != null);
|
||||
public boolean canInteract(Team team, Team other){
|
||||
return team == other || other == Team.derelict;
|
||||
}
|
||||
|
||||
public static class TeamData{
|
||||
public final ObjectSet<Tile> cores = new ObjectSet<>();
|
||||
/** Do not modify. */
|
||||
public Array<TeamData> getActive(){
|
||||
return active;
|
||||
}
|
||||
|
||||
public void registerCore(CoreEntity core){
|
||||
TeamData data = get(core.getTeam());
|
||||
//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);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
public class TeamData{
|
||||
private final Array<CoreEntity> cores = new Array<>();
|
||||
|
||||
public final Team team;
|
||||
public Queue<BrokenBlock> brokenBlocks = new Queue<>();
|
||||
|
||||
public TeamData(Team team){
|
||||
this.team = team;
|
||||
}
|
||||
|
||||
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 TileEntity core(){
|
||||
return cores.first();
|
||||
}
|
||||
}
|
||||
|
||||
/** Represents a block made by this team that was destroyed somewhere on the map.
|
||||
|
||||
@@ -10,6 +10,7 @@ import arc.scene.ui.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.type.*;
|
||||
@@ -161,7 +162,7 @@ public class Tutorial{
|
||||
},
|
||||
withdraw(() -> event("withdraw")){
|
||||
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")),
|
||||
@@ -239,18 +240,18 @@ public class Tutorial{
|
||||
//utility
|
||||
|
||||
static void placeBlocks(){
|
||||
Tile core = state.teams.get(defaultTeam).cores.first();
|
||||
TileEntity core = state.teams.playerCores().first();
|
||||
for(int i = 0; i < blocksToBreak; i++){
|
||||
world.removeBlock(world.ltile(core.x + blockOffset, core.y + i));
|
||||
world.tile(core.x + blockOffset, core.y + i).setBlock(Blocks.scrapWall, defaultTeam);
|
||||
world.ltile(core.tile.x + blockOffset, core.tile.y + i).remove();
|
||||
world.tile(core.tile.x + blockOffset, core.tile.y + i).setBlock(Blocks.scrapWall, state.rules.defaultTeam);
|
||||
}
|
||||
}
|
||||
|
||||
static boolean blocksBroken(){
|
||||
Tile core = state.teams.get(defaultTeam).cores.first();
|
||||
TileEntity core = state.teams.playerCores().first();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -270,7 +271,7 @@ public class Tutorial{
|
||||
}
|
||||
|
||||
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.teams.get(state.rules.defaultTeam).noCores() ? 0 : state.teams.playerCores().first().items.get(item);
|
||||
}
|
||||
|
||||
static boolean toggled(String name){
|
||||
|
||||
@@ -10,13 +10,12 @@ import mindustry.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.input.*;
|
||||
import mindustry.type.Category;
|
||||
import mindustry.ui.Cicon;
|
||||
import mindustry.type.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.units.MechPad;
|
||||
import mindustry.world.meta.BlockFlag;
|
||||
import mindustry.world.blocks.units.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
@@ -95,17 +94,15 @@ public class OverlayRenderer{
|
||||
Lines.stroke(buildFadeTime * 2f);
|
||||
|
||||
if(buildFadeTime > 0.005f){
|
||||
for(Team enemy : state.teams.enemiesOf(player.getTeam())){
|
||||
for(Tile core : state.teams.get(enemy).cores){
|
||||
float dst = Mathf.dst(player.x, player.y, core.drawx(), core.drawy());
|
||||
if(dst < state.rules.enemyCoreBuildRadius * 1.5f){
|
||||
Draw.color(Color.darkGray);
|
||||
Lines.circle(core.drawx(), core.drawy() - 2, state.rules.enemyCoreBuildRadius);
|
||||
Draw.color(Pal.accent, enemy.color, 0.5f + Mathf.absin(Time.time(), 10f, 0.5f));
|
||||
Lines.circle(core.drawx(), core.drawy(), state.rules.enemyCoreBuildRadius);
|
||||
}
|
||||
state.teams.eachEnemyCore(player.getTeam(), core -> {
|
||||
float dst = core.dst(player);
|
||||
if(dst < state.rules.enemyCoreBuildRadius * 1.5f){
|
||||
Draw.color(Color.darkGray);
|
||||
Lines.circle(core.x, core.y - 2, state.rules.enemyCoreBuildRadius);
|
||||
Draw.color(Pal.accent, core.getTeam().color, 0.5f + Mathf.absin(Time.time(), 10f, 0.5f));
|
||||
Lines.circle(core.x, core.y, state.rules.enemyCoreBuildRadius);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Lines.stroke(2f);
|
||||
|
||||
@@ -397,7 +397,7 @@ public class DesktopInput extends InputHandler{
|
||||
}
|
||||
|
||||
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;
|
||||
overrideLineRotation = true;
|
||||
}
|
||||
|
||||
@@ -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.maps.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.LegacyColorMapper.*;
|
||||
import mindustry.world.blocks.storage.*;
|
||||
|
||||
import java.io.*;
|
||||
@@ -91,7 +92,7 @@ public class MapIO{
|
||||
public void setTeam(Team team){
|
||||
super.setTeam(team);
|
||||
if(block instanceof CoreBlock){
|
||||
map.teams.add((int) team.id);
|
||||
map.teams.add((int)team.id);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -150,6 +151,28 @@ public class MapIO{
|
||||
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{
|
||||
Tile get(int x, int y);
|
||||
}
|
||||
|
||||
@@ -217,7 +217,7 @@ public abstract class SaveVersion extends SaveFileReader{
|
||||
Array<TeamData> data = state.teams.getActive();
|
||||
stream.writeInt(data.size);
|
||||
for(TeamData team : data){
|
||||
stream.writeInt((int) team.team.id);
|
||||
stream.writeInt((int)team.team.id);
|
||||
stream.writeInt(team.brokenBlocks.size);
|
||||
for(BrokenBlock block : team.brokenBlocks){
|
||||
stream.writeShort(block.x);
|
||||
@@ -258,7 +258,7 @@ public abstract class SaveVersion extends SaveFileReader{
|
||||
public void readEntities(DataInput stream) throws IOException{
|
||||
int teamc = stream.readInt();
|
||||
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);
|
||||
int blocks = stream.readInt();
|
||||
for(int j = 0; j < blocks; j++){
|
||||
|
||||
@@ -87,7 +87,7 @@ public class TypeIO{
|
||||
|
||||
@WriteClass(BaseUnit.class)
|
||||
public static void writeBaseUnit(ByteBuffer buffer, BaseUnit unit){
|
||||
buffer.put((byte) (int) unit.getTeam().id);
|
||||
buffer.put((byte) (int)unit.getTeam().id);
|
||||
buffer.putInt(unit.getID());
|
||||
}
|
||||
|
||||
@@ -95,7 +95,7 @@ public class TypeIO{
|
||||
public static BaseUnit readBaseUnit(ByteBuffer buffer){
|
||||
byte tid = buffer.get();
|
||||
int id = buffer.getInt();
|
||||
return unitGroups[tid].getByID(id);
|
||||
return unitGroup.getByID(id);
|
||||
}
|
||||
|
||||
@WriteClass(Tile.class)
|
||||
@@ -194,12 +194,12 @@ public class TypeIO{
|
||||
|
||||
@WriteClass(Team.class)
|
||||
public static void writeTeam(ByteBuffer buffer, Team reason){
|
||||
buffer.put((byte) (int) reason.id);
|
||||
buffer.put((byte) (int)reason.id);
|
||||
}
|
||||
|
||||
@ReadClass(Team.class)
|
||||
public static Team readTeam(ByteBuffer buffer){
|
||||
return Team.all[buffer.get()];
|
||||
return Team.get(buffer.get());
|
||||
}
|
||||
|
||||
@WriteClass(UnitCommand.class)
|
||||
|
||||
@@ -74,7 +74,7 @@ public class MapGenerator extends Generator{
|
||||
|
||||
for(int x = 0; x < width; x++){
|
||||
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));
|
||||
tiles[x][y].setBlock(Blocks.air);
|
||||
}
|
||||
|
||||
@@ -39,9 +39,9 @@ public class ItemsDisplay extends Table{
|
||||
private String format(Item item){
|
||||
builder.setLength(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) && state.teams.get(player.getTeam()).hasCore() && state.teams.get(player.getTeam()).core().items.get(item) > 0){
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -168,7 +168,7 @@ public class HudFragment extends Fragment{
|
||||
t.table(teams -> {
|
||||
teams.left();
|
||||
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))
|
||||
.size(50f).margin(6f).get();
|
||||
button.getImageCell().grow();
|
||||
@@ -287,7 +287,7 @@ public class HudFragment extends Fragment{
|
||||
});
|
||||
|
||||
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;
|
||||
return false;
|
||||
}
|
||||
@@ -628,7 +628,7 @@ public class HudFragment extends Fragment{
|
||||
}
|
||||
|
||||
if(state.rules.waveTimer){
|
||||
builder.append((state.rules.waitForWaveToEnd && unitGroups[(int) waveTeam.id].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){
|
||||
builder.append(Core.bundle.get("waiting"));
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import arc.scene.ui.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.util.*;
|
||||
import mindustry.core.GameState.*;
|
||||
import mindustry.entities.type.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.net.*;
|
||||
@@ -65,7 +66,7 @@ public class PlayerListFragment extends Fragment{
|
||||
|
||||
float h = 74f;
|
||||
|
||||
playerGroup.all().sort((p1, p2) -> p1.getTeam().compareTo(p2.getTeam()));
|
||||
playerGroup.all().sort(Structs.comparing(Unit::getTeam));
|
||||
playerGroup.all().each(user -> {
|
||||
NetConnection connection = user.con;
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ public class Build{
|
||||
Block previous = tile.block();
|
||||
Block sub = BuildBlock.get(previous.size);
|
||||
|
||||
world.setBlock(tile, sub, team, rotation);
|
||||
tile.set(sub, team, rotation);
|
||||
tile.<BuildEntity>ent().setDeconstruct(previous);
|
||||
tile.entity.health = tile.entity.maxHealth() * prevPercent;
|
||||
|
||||
@@ -60,7 +60,7 @@ public class Build{
|
||||
Block previous = tile.block();
|
||||
Block sub = BuildBlock.get(result.size);
|
||||
|
||||
world.setBlock(tile, sub, team, rotation);
|
||||
tile.set(sub, team, rotation);
|
||||
tile.<BuildEntity>ent().setConstruct(previous, result);
|
||||
|
||||
Core.app.post(() -> Events.fire(new BlockBuildBeginEvent(tile, team, false)));
|
||||
@@ -72,7 +72,7 @@ public class Build{
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -80,13 +80,8 @@ public class Build{
|
||||
return false;
|
||||
}
|
||||
|
||||
//check for enemy cores
|
||||
for(Team enemy : state.teams.enemiesOf(team)){
|
||||
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;
|
||||
}
|
||||
}
|
||||
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)){
|
||||
return false;
|
||||
}
|
||||
|
||||
Tile tile = world.tile(x, y);
|
||||
|
||||
@@ -16,7 +16,7 @@ public class CachedTile extends Tile{
|
||||
|
||||
@Override
|
||||
public Team getTeam(){
|
||||
return Team.all[getTeamID()];
|
||||
return Team.get(getTeamID());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -142,11 +142,11 @@ public class Tile implements Position, TargetTrait{
|
||||
|
||||
@Override
|
||||
public Team getTeam(){
|
||||
return Team.all[link().team];
|
||||
return Team.get(link().team);
|
||||
}
|
||||
|
||||
public void setTeam(Team team){
|
||||
this.team = (byte) (int) team.id;
|
||||
this.team = (byte) (int)team.id;
|
||||
}
|
||||
|
||||
public byte getTeamID(){
|
||||
@@ -156,7 +156,7 @@ public class Tile implements Position, TargetTrait{
|
||||
public void setBlock(@NonNull Block type, Team team, int rotation){
|
||||
preChanged();
|
||||
this.block = type;
|
||||
this.team = (byte) (int) team.id;
|
||||
this.team = (byte) (int)team.id;
|
||||
this.rotation = (byte)Mathf.mod(rotation, 4);
|
||||
changed();
|
||||
}
|
||||
@@ -186,6 +186,35 @@ public class Tile implements Position, TargetTrait{
|
||||
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(){
|
||||
return rotation;
|
||||
}
|
||||
@@ -240,7 +269,7 @@ public class Tile implements Position, TargetTrait{
|
||||
}
|
||||
|
||||
public boolean isEnemyCheat(){
|
||||
return getTeam() == waveTeam && state.rules.enemyCheat;
|
||||
return getTeam() == state.rules.waveTeam && state.rules.enemyCheat;
|
||||
}
|
||||
|
||||
public boolean isLinked(){
|
||||
@@ -344,7 +373,7 @@ public class Tile implements Position, TargetTrait{
|
||||
}
|
||||
|
||||
public boolean interactable(Team team){
|
||||
return getTeam() == Team.derelict || team == getTeam();
|
||||
return state.teams.canInteract(team, getTeam());
|
||||
}
|
||||
|
||||
public Item drop(){
|
||||
|
||||
@@ -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){
|
||||
if(tile == null) return;
|
||||
float healthf = tile.entity == null ? 1f : tile.entity.healthf();
|
||||
world.setBlock(tile, block, team, rotation);
|
||||
tile.set(block, team, rotation);
|
||||
if(tile.entity != null){
|
||||
tile.entity.health = block.health * healthf;
|
||||
}
|
||||
|
||||
@@ -84,12 +84,12 @@ public class CoreBlock extends StorageBlock{
|
||||
public void onProximityUpdate(Tile tile){
|
||||
CoreEntity entity = tile.ent();
|
||||
|
||||
for(Tile other : state.teams.get(tile.getTeam()).cores){
|
||||
if(other != tile){
|
||||
entity.items = other.entity.items;
|
||||
for(TileEntity other : state.teams.cores(tile.getTeam())){
|
||||
if(other.tile != tile){
|
||||
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.proximity().each(this::isContainer, t -> {
|
||||
@@ -97,9 +97,9 @@ public class CoreBlock extends StorageBlock{
|
||||
t.<StorageBlockEntity>ent().linkedCore = tile;
|
||||
});
|
||||
|
||||
for(Tile other : state.teams.get(tile.getTeam()).cores){
|
||||
if(other == tile) continue;
|
||||
entity.storageCapacity += other.block().itemCapacity + other.entity.proximity().sum(e -> isContainer(e) ? e.block().itemCapacity : 0);
|
||||
for(TileEntity other : state.teams.cores(tile.getTeam())){
|
||||
if(other.tile == tile) continue;
|
||||
entity.storageCapacity += other.block.itemCapacity + entity.proximity().sum(e -> isContainer(e) ? e.block().itemCapacity : 0);
|
||||
}
|
||||
|
||||
if(!world.isGenerating()){
|
||||
@@ -108,9 +108,8 @@ public class CoreBlock extends StorageBlock{
|
||||
}
|
||||
}
|
||||
|
||||
for(Tile other : state.teams.get(tile.getTeam()).cores){
|
||||
CoreEntity oe = other.ent();
|
||||
oe.storageCapacity = entity.storageCapacity;
|
||||
for(CoreEntity other : state.teams.cores(tile.getTeam())){
|
||||
other.storageCapacity = entity.storageCapacity;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,8 +150,9 @@ public class CoreBlock extends StorageBlock{
|
||||
|
||||
@Override
|
||||
public void removed(Tile tile){
|
||||
CoreEntity entity = tile.ent();
|
||||
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 -> {
|
||||
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()){
|
||||
tile.entity.items.set(item, Math.min(tile.entity.items.get(item), max));
|
||||
}
|
||||
|
||||
for(Tile other : state.teams.get(tile.getTeam()).cores){
|
||||
other.block().onProximityUpdate(other);
|
||||
for(CoreEntity other : state.teams.cores(tile.getTeam())){
|
||||
other.block.onProximityUpdate(other.tile);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void placed(Tile tile){
|
||||
super.placed(tile);
|
||||
state.teams.get(tile.getTeam()).cores.add(tile);
|
||||
CoreEntity entity = tile.ent();
|
||||
state.teams.registerCore(entity);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -58,7 +58,7 @@ public class CommandCenter extends Block{
|
||||
ObjectSet<Tile> set = indexer.getAllied(tile.getTeam(), BlockFlag.comandCenter);
|
||||
|
||||
if(set.size == 1){
|
||||
for(BaseUnit unit : unitGroups[(int) tile.getTeam().id].all()){
|
||||
for(BaseUnit unit : unitGroups[(int)tile.getTeam().id].all()){
|
||||
unit.onCommand(UnitCommand.all[0]);
|
||||
}
|
||||
}
|
||||
@@ -116,7 +116,7 @@ public class CommandCenter extends Block{
|
||||
|
||||
Team team = (player == null ? tile.getTeam() : player.getTeam());
|
||||
|
||||
for(BaseUnit unit : unitGroups[(int) team.id].all()){
|
||||
for(BaseUnit unit : unitGroups[(int)team.id].all()){
|
||||
unit.onCommand(command);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user