Merging changes from private branch
This commit is contained in:
@@ -9,6 +9,7 @@ import mindustry.net.*;
|
||||
import mindustry.net.Packets.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.environment.*;
|
||||
import mindustry.world.blocks.storage.CoreBlock.*;
|
||||
|
||||
public class EventType{
|
||||
@@ -82,6 +83,8 @@ public class EventType{
|
||||
public static class BlockInfoEvent{}
|
||||
/** Called *after* all content has been initialized. */
|
||||
public static class ContentInitEvent{}
|
||||
/** Called *after* all content has been added to the atlas, but before its pixmaps are disposed. */
|
||||
public static class AtlasPackEvent{}
|
||||
/** Called *after* all mod content has been loaded, but before it has been initialized. */
|
||||
public static class ModContentLoadEvent{}
|
||||
/** Called when the client game is first loaded. */
|
||||
@@ -395,6 +398,22 @@ public class EventType{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a tile changes its floor. Do not cache or use with a timer.
|
||||
* Do not modify any tiles inside listener code.
|
||||
* */
|
||||
public static class TileFloorChangeEvent{
|
||||
public Tile tile;
|
||||
public Floor previous, floor;
|
||||
|
||||
public TileFloorChangeEvent set(Tile tile, Floor previous, Floor floor){
|
||||
this.tile = tile;
|
||||
this.previous = previous;
|
||||
this.floor = floor;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after a building's team changes.
|
||||
* Event object is reused, do not nest!
|
||||
|
||||
@@ -36,6 +36,7 @@ public final class FogControl implements CustomChunk{
|
||||
|
||||
private boolean justLoaded = false;
|
||||
private boolean loadedStatic = false;
|
||||
private int lastEntityUpdateIndex = 0;
|
||||
|
||||
public FogControl(){
|
||||
Events.on(ResetEvent.class, e -> {
|
||||
@@ -131,6 +132,7 @@ public final class FogControl implements CustomChunk{
|
||||
}
|
||||
|
||||
void stop(){
|
||||
lastEntityUpdateIndex = 0;
|
||||
fog = null;
|
||||
//I don't care whether the fog thread crashes here, it's about to die anyway
|
||||
staticEvents.clear();
|
||||
@@ -214,6 +216,31 @@ public final class FogControl implements CustomChunk{
|
||||
//clear to prepare for queuing fog radius from units and buildings
|
||||
dynamicEventQueue.clear();
|
||||
|
||||
//update fog visibility manually
|
||||
if(state.rules.fog && !headless && Groups.build.size() > 0){
|
||||
|
||||
int size = Groups.build.size();
|
||||
int chunkSize = 5; //fraction of entity list to iterate each frame
|
||||
int chunks = Math.min(chunkSize, size);
|
||||
|
||||
int iterated = Math.max(1, size / chunks);
|
||||
int steps = 0;
|
||||
int i = lastEntityUpdateIndex % size;
|
||||
|
||||
while(steps < iterated){
|
||||
Groups.build.index(i).updateFogVisibility();
|
||||
|
||||
steps ++;
|
||||
i ++;
|
||||
|
||||
if(i >= size){
|
||||
i = 0;
|
||||
}
|
||||
}
|
||||
|
||||
lastEntityUpdateIndex = i;
|
||||
}
|
||||
|
||||
for(var team : state.teams.present){
|
||||
//AI teams do not have fog
|
||||
if(!team.team.isOnlyAI()){
|
||||
|
||||
@@ -277,6 +277,11 @@ public class MapObjectives implements Iterable<MapObjective>, Eachable<MapObject
|
||||
String className = getClass().getSimpleName().replace("Objective", "");
|
||||
return Core.bundle == null ? className : Core.bundle.get("objective." + className.toLowerCase() + ".name", className);
|
||||
}
|
||||
|
||||
/** Validate fields after reading to make sure none of them are null. */
|
||||
public void validate(){
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/** Research a specific piece of content in the tech tree. */
|
||||
@@ -298,6 +303,11 @@ public class MapObjectives implements Iterable<MapObjective>, Eachable<MapObject
|
||||
public String text(){
|
||||
return Core.bundle.format("objective.research", content.emoji(), content.localizedName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate(){
|
||||
if(content == null) content = Items.copper;
|
||||
}
|
||||
}
|
||||
|
||||
/** Produce a specific piece of content in the tech tree (essentially research with different text). */
|
||||
@@ -319,6 +329,11 @@ public class MapObjectives implements Iterable<MapObjective>, Eachable<MapObject
|
||||
public String text(){
|
||||
return Core.bundle.format("objective.produce", content.emoji(), content.localizedName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate(){
|
||||
if(content == null) content = Items.copper;
|
||||
}
|
||||
}
|
||||
|
||||
/** Have a certain amount of item in your core. */
|
||||
@@ -342,6 +357,11 @@ public class MapObjectives implements Iterable<MapObjective>, Eachable<MapObject
|
||||
public String text(){
|
||||
return Core.bundle.format("objective.item", state.rules.defaultTeam.items().get(item), amount, item.emoji(), item.localizedName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate(){
|
||||
if(item == null) item = Items.copper;
|
||||
}
|
||||
}
|
||||
|
||||
/** Get a certain item in your core (through a block, not manually.) */
|
||||
@@ -365,6 +385,11 @@ public class MapObjectives implements Iterable<MapObjective>, Eachable<MapObject
|
||||
public String text(){
|
||||
return Core.bundle.format("objective.coreitem", state.stats.coreItemCount.get(item), amount, item.emoji(), item.localizedName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate(){
|
||||
if(item == null) item = Items.copper;
|
||||
}
|
||||
}
|
||||
|
||||
/** Build a certain amount of a block. */
|
||||
@@ -388,6 +413,11 @@ public class MapObjectives implements Iterable<MapObjective>, Eachable<MapObject
|
||||
public String text(){
|
||||
return Core.bundle.format("objective.build", count - state.stats.placedBlockCount.get(block, 0), block.emoji(), block.localizedName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate(){
|
||||
if(block == null) block = Blocks.conveyor;
|
||||
}
|
||||
}
|
||||
|
||||
/** Produce a certain amount of a unit. */
|
||||
@@ -411,6 +441,11 @@ public class MapObjectives implements Iterable<MapObjective>, Eachable<MapObject
|
||||
public String text(){
|
||||
return Core.bundle.format("objective.buildunit", count - state.rules.defaultTeam.data().countType(unit), unit.emoji(), unit.localizedName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate(){
|
||||
if(unit == null) unit = UnitTypes.dagger;
|
||||
}
|
||||
}
|
||||
|
||||
/** Produce a certain amount of units. */
|
||||
@@ -524,6 +559,11 @@ public class MapObjectives implements Iterable<MapObjective>, Eachable<MapObject
|
||||
public String text(){
|
||||
return Core.bundle.format("objective.destroyblock", block.emoji(), block.localizedName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate(){
|
||||
if(block == null) block = Blocks.router;
|
||||
}
|
||||
}
|
||||
|
||||
public static class DestroyBlocksObjective extends MapObjective{
|
||||
@@ -559,6 +599,11 @@ public class MapObjectives implements Iterable<MapObjective>, Eachable<MapObject
|
||||
public String text(){
|
||||
return Core.bundle.format("objective.destroyblocks", progress(), positions.length, block.emoji(), block.localizedName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void validate(){
|
||||
if(block == null) block = Blocks.router;
|
||||
}
|
||||
}
|
||||
|
||||
/** Command any unit to do anything. Always compete in headless mode. */
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package mindustry.game;
|
||||
|
||||
import arc.func.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import arc.util.serialization.*;
|
||||
import arc.util.serialization.Json.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.ctype.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.io.versions.*;
|
||||
import mindustry.type.*;
|
||||
@@ -48,6 +48,8 @@ public class SpawnGroup implements JsonSerializable, Cloneable{
|
||||
public @Nullable StatusEffect effect;
|
||||
/** Items this unit spawns with. Null to disable. */
|
||||
public @Nullable ItemStack items;
|
||||
/** Team that units spawned use. Null for default wave team. */
|
||||
public @Nullable Team team;
|
||||
|
||||
public SpawnGroup(UnitType type){
|
||||
this.type = type;
|
||||
@@ -75,12 +77,9 @@ public class SpawnGroup implements JsonSerializable, Cloneable{
|
||||
return Math.max(shields + shieldScaling*(wave - begin), 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a unit, and assigns correct values based on this group's data.
|
||||
* This method does not add() the unit.
|
||||
*/
|
||||
public Unit createUnit(Team team, int wave){
|
||||
Unit unit = type.create(team);
|
||||
/** Creates a unit, and assigns correct values based on this group's data. */
|
||||
public Unit createUnit(Team team, float x, float y, float rotation, int wave, Cons<Unit> cons){
|
||||
Unit unit = type.spawn(team, x, y, rotation, cons);
|
||||
|
||||
if(effect != null){
|
||||
unit.apply(effect, 999999f);
|
||||
@@ -104,6 +103,11 @@ public class SpawnGroup implements JsonSerializable, Cloneable{
|
||||
return unit;
|
||||
}
|
||||
|
||||
/** Creates a unit, and assigns correct values based on this group's data. */
|
||||
public Unit createUnit(Team team, int wave){
|
||||
return createUnit(team, 0f, 0f, 0f, wave, u -> {});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(Json json){
|
||||
if(type == null) type = UnitTypes.dagger;
|
||||
@@ -120,7 +124,7 @@ public class SpawnGroup implements JsonSerializable, Cloneable{
|
||||
if(spawn != -1) json.writeValue("spawn", spawn);
|
||||
if(payloads != null && payloads.any()) json.writeValue("payloads", payloads.map(u -> u.name).toArray(String.class));
|
||||
if(items != null && items.amount > 0) json.writeValue("items", items);
|
||||
|
||||
if(team != null) json.writeValue("team", team.id);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -140,6 +144,7 @@ public class SpawnGroup implements JsonSerializable, Cloneable{
|
||||
spawn = data.getInt("spawn", -1);
|
||||
if(data.has("payloads")) payloads = Seq.with(json.readValue(String[].class, data.get("payloads"))).map(content::unit).removeAll(t -> t == null);
|
||||
if(data.has("items")) items = json.readValue(ItemStack.class, data.get("items"));
|
||||
if(data.has("team")) team = Team.get(data.getInt("team"));
|
||||
|
||||
|
||||
//old boss effect ID
|
||||
|
||||
@@ -19,6 +19,7 @@ public class Team implements Comparable<Team>, Senseable{
|
||||
public final Color color = new Color();
|
||||
public final Color[] palette = {new Color(), new Color(), new Color()};
|
||||
public final int[] palettei = new int[3];
|
||||
public boolean ignoreUnitCap = false;
|
||||
public String emoji = "";
|
||||
public boolean hasPalette;
|
||||
public String name;
|
||||
@@ -50,6 +51,8 @@ public class Team implements Comparable<Team>, Senseable{
|
||||
new Team(i, "team#" + i, Color.HSVtoRGB(360f * Mathf.random(), 100f * Mathf.random(0.4f, 1f), 100f * Mathf.random(0.6f, 1f), 1f));
|
||||
}
|
||||
Mathf.rand.setSeed(new Rand().nextLong());
|
||||
|
||||
neoplastic.ignoreUnitCap = true;
|
||||
}
|
||||
|
||||
public static Team get(int id){
|
||||
@@ -95,10 +98,16 @@ public class Team implements Comparable<Team>, Senseable{
|
||||
return data().core();
|
||||
}
|
||||
|
||||
/** @return whether this team has any buildings on this map; in waves mode, this is always true for the enemy team. */
|
||||
public boolean active(){
|
||||
return state.teams.isActive(this);
|
||||
}
|
||||
|
||||
/** @return whether this team has any active cores. Not the same as active()! */
|
||||
public boolean isAlive(){
|
||||
return data().isAlive();
|
||||
}
|
||||
|
||||
/** @return whether this team is supposed to be AI-controlled. */
|
||||
public boolean isAI(){
|
||||
return (state.rules.waves || state.rules.attackMode) && this != state.rules.defaultTeam && !state.rules.pvp;
|
||||
@@ -114,12 +123,6 @@ public class Team implements Comparable<Team>, Senseable{
|
||||
return isAI() && !rules().rtsAi;
|
||||
}
|
||||
|
||||
/** @deprecated There is absolutely no reason to use this. */
|
||||
@Deprecated
|
||||
public boolean isEnemy(Team other){
|
||||
return this != other;
|
||||
}
|
||||
|
||||
public Seq<CoreBuild> cores(){
|
||||
return state.teams.cores(this);
|
||||
}
|
||||
@@ -161,6 +164,7 @@ public class Team implements Comparable<Team>, Senseable{
|
||||
@Override
|
||||
public double sense(LAccess sensor){
|
||||
if(sensor == LAccess.id) return id;
|
||||
return 0;
|
||||
if(sensor == LAccess.color) return color.toDoubleBits();
|
||||
return Double.NaN;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,6 +126,15 @@ public class Teams{
|
||||
return active;
|
||||
}
|
||||
|
||||
public void updateActive(Team team){
|
||||
TeamData data = get(team);
|
||||
//register in active list if needed
|
||||
if(data.active() && !active.contains(data)){
|
||||
active.add(data);
|
||||
updateEnemies();
|
||||
}
|
||||
}
|
||||
|
||||
public void registerCore(CoreBuild core){
|
||||
TeamData data = get(core.team);
|
||||
//add core if not present
|
||||
@@ -407,13 +416,18 @@ public class Teams{
|
||||
}
|
||||
|
||||
public boolean active(){
|
||||
return (team == state.rules.waveTeam && state.rules.waves) || cores.size > 0;
|
||||
return (team == state.rules.waveTeam && state.rules.waves) || cores.size > 0 || buildings.size > 0 || (team == Team.neoplastic && units.size > 0);
|
||||
}
|
||||
|
||||
public boolean hasCore(){
|
||||
return cores.size > 0;
|
||||
}
|
||||
|
||||
/** @return whether this team has any cores (standard team), or any hearts (neoplasm). */
|
||||
public boolean isAlive(){
|
||||
return hasCore();
|
||||
}
|
||||
|
||||
public boolean noCores(){
|
||||
return cores.isEmpty();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user