Update.
This commit is contained in:
Binary file not shown.
@@ -47,6 +47,8 @@ public class Vars implements Loadable{
|
||||
public static final int bufferSize = 8192;
|
||||
/** global charset, since Android doesn't support the Charsets class */
|
||||
public static final Charset charset = Charset.forName("UTF-8");
|
||||
/** mods suggested for import */
|
||||
public static final String[] suggestedMods = {""};
|
||||
/** main application name, capitalized */
|
||||
public static final String appName = "Mindustry";
|
||||
/** URL for itch.io donations. */
|
||||
@@ -56,7 +58,7 @@ public class Vars implements Loadable{
|
||||
/** URL for sending crash reports to */
|
||||
public static final String crashReportURL = "http://192.99.169.18/report";
|
||||
/** URL the links to the wiki's modding guide.*/
|
||||
public static final String modGuideURL = "https://mindustrygame.github.io/wiki/modding/";
|
||||
public static final String modGuideURL = "https://mindustrygame.github.io/wiki/modding/1-modding/";
|
||||
/** URL to the JSON file containing all the global, public servers. Not queried in BE. */
|
||||
public static final String serverJsonURL = "https://raw.githubusercontent.com/Anuken/Mindustry/master/servers.json";
|
||||
/** URL to the JSON file containing all the BE servers. Only queried in BE. */
|
||||
|
||||
@@ -13,6 +13,7 @@ import mindustry.game.EventType.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.storage.*;
|
||||
import mindustry.world.meta.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
@@ -115,7 +116,7 @@ public class Pathfinder implements Runnable{
|
||||
}
|
||||
|
||||
return PathTile.get(
|
||||
tile.build == null || !tile.solid() ? 0 : Math.min((int)(tile.build.health / 40), 80),
|
||||
tile.build == null || !tile.solid() || tile.block() instanceof CoreBlock ? 0 : Math.min((int)(tile.build.health / 40), 80),
|
||||
tile.getTeamID(),
|
||||
tile.solid(),
|
||||
tile.floor().isLiquid,
|
||||
@@ -458,7 +459,7 @@ public class Pathfinder implements Runnable{
|
||||
/** costs of getting to a specific tile */
|
||||
public int[][] weights;
|
||||
/** search IDs of each position - the highest, most recent search is prioritized and overwritten */
|
||||
int[][] searches;
|
||||
public int[][] searches;
|
||||
/** search frontier, these are Pos objects */
|
||||
IntQueue frontier = new IntQueue();
|
||||
/** all target positions; these positions have a cost of 0, and must be synchronized on! */
|
||||
|
||||
@@ -1657,6 +1657,7 @@ public class UnitTypes implements ContentList{
|
||||
recoil = 3f;
|
||||
occlusion = 12f;
|
||||
ejectEffect = Fx.casing3;
|
||||
shootSound = Sounds.shootBig;
|
||||
|
||||
shots = 3;
|
||||
shotDelay = 4f;
|
||||
|
||||
@@ -340,7 +340,7 @@ public class Control implements ApplicationListener, Loadable{
|
||||
state.rules.waves = true;
|
||||
|
||||
//reset win wave??
|
||||
state.rules.winWave = state.rules.attackMode ? -1 : sector.preset != null ? sector.preset.captureWave : 40;
|
||||
state.rules.winWave = state.rules.attackMode ? -1 : sector.preset != null ? sector.preset.captureWave : state.rules.winWave > state.wave ? state.rules.winWave : 40;
|
||||
|
||||
//if there's still an enemy base left, fix it
|
||||
if(state.rules.attackMode){
|
||||
|
||||
@@ -258,11 +258,11 @@ public class UI implements ApplicationListener, Loadable{
|
||||
TextField field = cont.field(def, t -> {}).size(330f, 50f).get();
|
||||
field.setFilter((f, c) -> field.getText().length() < textLength && filter.acceptChar(f, c));
|
||||
buttons.defaults().size(120, 54).pad(4);
|
||||
buttons.button("@cancel", this::hide);
|
||||
buttons.button("@ok", () -> {
|
||||
confirmed.get(field.getText());
|
||||
hide();
|
||||
}).disabled(b -> field.getText().isEmpty());
|
||||
buttons.button("@cancel", this::hide);
|
||||
keyDown(KeyCode.enter, () -> {
|
||||
String text = field.getText();
|
||||
if(!text.isEmpty()){
|
||||
|
||||
@@ -53,7 +53,7 @@ public class Lightning{
|
||||
world.raycastEach(World.toTile(from.getX()), World.toTile(from.getY()), World.toTile(to.getX()), World.toTile(to.getY()), (wx, wy) -> {
|
||||
|
||||
Tile tile = world.tile(wx, wy);
|
||||
if(tile != null && tile.block().insulated){
|
||||
if(tile != null && tile.block().insulated && tile.team() != team){
|
||||
bhit = true;
|
||||
//snap it instead of removing
|
||||
lines.get(lines.size -1).set(wx * tilesize, wy * tilesize);
|
||||
|
||||
@@ -30,7 +30,7 @@ public class RepairFieldAbility extends Ability{
|
||||
|
||||
Units.nearby(unit.team, unit.x, unit.y, range, other -> {
|
||||
if(other.damaged()){
|
||||
healEffect.at(unit);
|
||||
healEffect.at(other);
|
||||
wasHealed = true;
|
||||
}
|
||||
other.heal(amount);
|
||||
|
||||
@@ -16,11 +16,13 @@ abstract class BoundedComp implements Velc, Posc, Healthc, Flyingc{
|
||||
|
||||
@Override
|
||||
public void update(){
|
||||
//repel unit out of bounds
|
||||
if(x < 0) vel.x += (-x/warpDst);
|
||||
if(y < 0) vel.y += (-y/warpDst);
|
||||
if(x > world.unitWidth()) vel.x -= (x - world.unitWidth())/warpDst;
|
||||
if(y > world.unitHeight()) vel.y -= (y - world.unitHeight())/warpDst;
|
||||
if(!net.client() || isLocal()){
|
||||
//repel unit out of bounds
|
||||
if(x < 0) vel.x += (-x/warpDst);
|
||||
if(y < 0) vel.y += (-y/warpDst);
|
||||
if(x > world.unitWidth()) vel.x -= (x - world.unitWidth())/warpDst;
|
||||
if(y > world.unitHeight()) vel.y -= (y - world.unitHeight())/warpDst;
|
||||
}
|
||||
|
||||
//clamp position if not flying
|
||||
if(isGrounded()){
|
||||
|
||||
@@ -11,6 +11,7 @@ import mindustry.annotations.Annotations.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.units.*;
|
||||
import mindustry.game.EventType.*;
|
||||
import mindustry.game.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.type.*;
|
||||
@@ -28,6 +29,7 @@ abstract class BuilderComp implements Posc, Teamc, Rotc{
|
||||
|
||||
@Import float x, y, rotation;
|
||||
@Import UnitType type;
|
||||
@Import Team team;
|
||||
|
||||
@SyncLocal Queue<BuildPlan> plans = new Queue<>(1);
|
||||
@SyncLocal transient boolean updateBuilding = true;
|
||||
@@ -75,27 +77,27 @@ abstract class BuilderComp implements Posc, Teamc, Rotc{
|
||||
Tile tile = world.tile(current.x, current.y);
|
||||
|
||||
if(!(tile.block() instanceof ConstructBlock)){
|
||||
if(!current.initialized && !current.breaking && Build.validPlace(current.block, team(), current.x, current.y, current.rotation)){
|
||||
if(!current.initialized && !current.breaking && Build.validPlace(current.block, team, current.x, current.y, current.rotation)){
|
||||
boolean hasAll = infinite || !Structs.contains(current.block.requirements, i -> core != null && !core.items.has(i.item));
|
||||
|
||||
if(hasAll){
|
||||
Call.beginPlace(current.block, team(), current.x, current.y, current.rotation);
|
||||
Call.beginPlace(self(), current.block, team, current.x, current.y, current.rotation);
|
||||
}else{
|
||||
current.stuck = true;
|
||||
}
|
||||
}else if(!current.initialized && current.breaking && Build.validBreak(team(), current.x, current.y)){
|
||||
Call.beginBreak(team(), current.x, current.y);
|
||||
}else if(!current.initialized && current.breaking && Build.validBreak(team, current.x, current.y)){
|
||||
Call.beginBreak(self(), team, current.x, current.y);
|
||||
}else{
|
||||
plans.removeFirst();
|
||||
return;
|
||||
}
|
||||
}else if(tile.team() != team()){
|
||||
}else if(tile.team() != team){
|
||||
plans.removeFirst();
|
||||
return;
|
||||
}
|
||||
|
||||
if(tile.build instanceof ConstructBuild && !current.initialized){
|
||||
Core.app.post(() -> Events.fire(new BuildSelectEvent(tile, team(), (Builderc)this, current.breaking)));
|
||||
Core.app.post(() -> Events.fire(new BuildSelectEvent(tile, team, self(), current.breaking)));
|
||||
current.initialized = true;
|
||||
}
|
||||
|
||||
@@ -128,7 +130,7 @@ abstract class BuilderComp implements Posc, Teamc, Rotc{
|
||||
control.input.drawBreaking(request);
|
||||
}else{
|
||||
request.block.drawRequest(request, control.input.allRequests(),
|
||||
Build.validPlace(request.block, team(), request.x, request.y, request.rotation) || control.input.requestMatches(request));
|
||||
Build.validPlace(request.block, team, request.x, request.y, request.rotation) || control.input.requestMatches(request));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,7 +140,7 @@ abstract class BuilderComp implements Posc, Teamc, Rotc{
|
||||
/** @return whether this request should be skipped, in favor of the next one. */
|
||||
boolean shouldSkip(BuildPlan request, @Nullable Building core){
|
||||
//requests that you have at least *started* are considered
|
||||
if(state.rules.infiniteResources || team().rules().infiniteResources || request.breaking || core == null) return false;
|
||||
if(state.rules.infiniteResources || team.rules().infiniteResources || request.breaking || core == null) return false;
|
||||
return (request.stuck && !core.items.has(request.block.requirements)) || (Structs.contains(request.block.requirements, i -> !core.items.has(i.item) && Mathf.round(i.amount * state.rules.buildCostMultiplier) > 0) && !request.initialized);
|
||||
}
|
||||
|
||||
|
||||
@@ -90,8 +90,8 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
||||
public float prefRotation(){
|
||||
if(activelyBuilding()){
|
||||
return angleTo(buildPlan());
|
||||
}else if(mineTile() != null){
|
||||
return angleTo(mineTile());
|
||||
}else if(mineTile != null){
|
||||
return angleTo(mineTile);
|
||||
}else if(moving()){
|
||||
return vel().angle();
|
||||
}
|
||||
@@ -310,7 +310,7 @@ abstract class UnitComp implements Healthc, Physicsc, Hitboxc, Statusc, Teamc, I
|
||||
drag = type.drag * (isGrounded() ? (floorOn().dragMultiplier) : 1f);
|
||||
|
||||
//apply knockback based on spawns
|
||||
if(team != state.rules.waveTeam && state.hasSpawns()){
|
||||
if(team != state.rules.waveTeam && state.hasSpawns() && (!net.client() || isLocal())){
|
||||
float relativeSize = state.rules.dropZoneRadius + hitSize/2f + 1f;
|
||||
for(Tile spawn : spawner.getSpawns()){
|
||||
if(within(spawn.worldx(), spawn.worldy(), relativeSize)){
|
||||
|
||||
@@ -278,11 +278,13 @@ public class EventType{
|
||||
public static class BlockBuildBeginEvent{
|
||||
public final Tile tile;
|
||||
public final Team team;
|
||||
public final @Nullable Unit unit;
|
||||
public final boolean breaking;
|
||||
|
||||
public BlockBuildBeginEvent(Tile tile, Team team, boolean breaking){
|
||||
public BlockBuildBeginEvent(Tile tile, Team team, Unit unit, boolean breaking){
|
||||
this.tile = tile;
|
||||
this.team = team;
|
||||
this.unit = unit;
|
||||
this.breaking = breaking;
|
||||
}
|
||||
}
|
||||
@@ -310,10 +312,10 @@ public class EventType{
|
||||
public static class BuildSelectEvent{
|
||||
public final Tile tile;
|
||||
public final Team team;
|
||||
public final Builderc builder;
|
||||
public final Unit builder;
|
||||
public final boolean breaking;
|
||||
|
||||
public BuildSelectEvent(Tile tile, Team team, Builderc builder, boolean breaking){
|
||||
public BuildSelectEvent(Tile tile, Team team, Unit builder, boolean breaking){
|
||||
this.tile = tile;
|
||||
this.team = team;
|
||||
this.builder = builder;
|
||||
|
||||
@@ -225,9 +225,11 @@ public class Universe{
|
||||
if(sector.isBeingPlayed()){
|
||||
state.rules.winWave = waveMax;
|
||||
state.rules.waves = true;
|
||||
state.rules.attackMode = false;
|
||||
}else{
|
||||
sector.info.winWave = waveMax;
|
||||
sector.info.waves = true;
|
||||
sector.info.attack = false;
|
||||
sector.saveInfo();
|
||||
}
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ public class PlanetRenderer implements Disposable{
|
||||
public final VertexBatch3D batch = new VertexBatch3D(20000, false, true, 0);
|
||||
|
||||
public float zoom = 1f;
|
||||
public float orbitAlpha = 1f;
|
||||
|
||||
private final Mesh[] outlines = new Mesh[10];
|
||||
public final PlaneBatch3D projector = new PlaneBatch3D();
|
||||
@@ -168,7 +169,7 @@ public class PlanetRenderer implements Disposable{
|
||||
Vec3 center = planet.parent.position;
|
||||
float radius = planet.orbitRadius;
|
||||
int points = (int)(radius * 10);
|
||||
Angles.circleVectors(points, radius, (cx, cy) -> batch.vertex(Tmp.v32.set(center).add(cx, 0, cy), Pal.gray));
|
||||
Angles.circleVectors(points, radius, (cx, cy) -> batch.vertex(Tmp.v32.set(center).add(cx, 0, cy), Pal.gray.write(Tmp.c1).a(orbitAlpha)));
|
||||
batch.flush(Gl.lineLoop);
|
||||
}
|
||||
|
||||
|
||||
@@ -629,8 +629,8 @@ public class DesktopInput extends InputHandler{
|
||||
unit.moveAt(movement);
|
||||
}else{
|
||||
unit.moveAt(Tmp.v2.trns(unit.rotation, movement.len()));
|
||||
if(!movement.isZero() && ground){
|
||||
unit.vel.rotateTo(movement.angle(), unit.type.rotateSpeed);
|
||||
if(!movement.isZero()){
|
||||
unit.vel.rotateTo(movement.angle(), unit.type.rotateSpeed * Math.max(Time.delta, 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -769,7 +769,7 @@ public class MobileInput extends InputHandler implements GestureListener{
|
||||
|
||||
@Override
|
||||
public boolean pan(float x, float y, float deltaX, float deltaY){
|
||||
if(Core.scene.hasDialog() || Core.settings.getBool("keyboard")) return false;
|
||||
if(Core.scene == null || Core.scene.hasDialog() || Core.settings.getBool("keyboard")) return false;
|
||||
|
||||
float scale = Core.camera.width / Core.graphics.getWidth();
|
||||
deltaX *= scale;
|
||||
@@ -836,7 +836,7 @@ public class MobileInput extends InputHandler implements GestureListener{
|
||||
if(type == null) return;
|
||||
|
||||
boolean omni = unit.type.omniMovement;
|
||||
boolean legs = unit.isGrounded();
|
||||
boolean ground = unit.isGrounded();
|
||||
boolean allowHealing = type.canHeal;
|
||||
boolean validHealTarget = allowHealing && target instanceof Building && ((Building)target).isValid() && target.team() == unit.team &&
|
||||
((Building)target).damaged() && target.within(unit, type.range);
|
||||
@@ -908,8 +908,8 @@ public class MobileInput extends InputHandler implements GestureListener{
|
||||
unit.moveAt(movement);
|
||||
}else{
|
||||
unit.moveAt(Tmp.v2.trns(unit.rotation, movement.len()));
|
||||
if(!movement.isZero() && legs){
|
||||
unit.vel.rotateTo(movement.angle(), type.rotateSpeed);
|
||||
if(!movement.isZero()){
|
||||
unit.vel.rotateTo(movement.angle(), unit.type.rotateSpeed * Math.max(Time.delta, 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -309,6 +309,10 @@ public class ContentParser{
|
||||
|
||||
}
|
||||
|
||||
if(value.has("controller")){
|
||||
unit.defaultController = make(resolve(value.getString("controller"), "mindustry.ai.type"));
|
||||
}
|
||||
|
||||
//read extra default waves
|
||||
if(value.has("waves")){
|
||||
JsonValue waves = value.remove("waves");
|
||||
|
||||
@@ -19,7 +19,7 @@ import mindustry.world.blocks.*;
|
||||
|
||||
import static mindustry.Vars.*;
|
||||
|
||||
public abstract class Weather extends UnlockableContent{
|
||||
public class Weather extends UnlockableContent{
|
||||
/** Default duration of this weather event in ticks. */
|
||||
public float duration = 10f * Time.toMinutes;
|
||||
public float opacityMultiplier = 1f;
|
||||
|
||||
@@ -102,12 +102,16 @@ public class ModsDialog extends BaseDialog{
|
||||
|
||||
t.button("@mod.import.github", Icon.github, bstyle, () -> {
|
||||
dialog.hide();
|
||||
var modString = Core.settings.getString("lastmod", "");
|
||||
var suggested = Structs.random(suggestedMods);
|
||||
|
||||
ui.showTextInput("@mod.import.github", "", 64, Core.settings.getString("lastmod", "Anuken/ExampleMod"), text -> {
|
||||
Core.settings.put("lastmod", text);
|
||||
ui.showTextInput("@mod.import.github", "", 64, modString.isEmpty() ? suggested : modString, text -> {
|
||||
if(!modString.isEmpty() || !Structs.eq(suggested, text)){
|
||||
Core.settings.put("lastmod", text);
|
||||
}
|
||||
|
||||
ui.loadfrag.show();
|
||||
//Try to download the 6.0 branch first, but if it doesn't exist try master.
|
||||
//Try to download the 6.0 branch first, but if it doesn't exist, try master.
|
||||
githubImport("6.0", text, e1 -> {
|
||||
githubImport("master", text, e2 -> {
|
||||
githubImport("main", text, e3 -> {
|
||||
|
||||
@@ -409,6 +409,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
||||
|
||||
@Override
|
||||
public void draw(){
|
||||
planets.orbitAlpha = selectAlpha;
|
||||
planets.render(PlanetDialog.this);
|
||||
if(Core.scene.getDialog() == PlanetDialog.this){
|
||||
Core.scene.setScrollFocus(PlanetDialog.this);
|
||||
@@ -711,6 +712,7 @@ public class PlanetDialog extends BaseDialog implements PlanetInterfaceRenderer{
|
||||
stable.table(t -> {
|
||||
t.add("@sectors.resources").padRight(4);
|
||||
for(UnlockableContent c : sector.info.resources){
|
||||
if(c == null) continue; //apparently this is possible.
|
||||
t.image(c.icon(Cicon.small)).padRight(3).size(Cicon.small.size);
|
||||
}
|
||||
}).padLeft(10f).fillX().row();
|
||||
|
||||
@@ -20,7 +20,7 @@ public class Build{
|
||||
private static final IntSet tmp = new IntSet();
|
||||
|
||||
@Remote(called = Loc.server)
|
||||
public static void beginBreak(Team team, int x, int y){
|
||||
public static void beginBreak(@Nullable Unit unit, Team team, int x, int y){
|
||||
if(!validBreak(team, x, y)){
|
||||
return;
|
||||
}
|
||||
@@ -40,14 +40,14 @@ public class Build{
|
||||
tile.setBlock(sub, team, rotation);
|
||||
tile.<ConstructBuild>bc().setDeconstruct(previous);
|
||||
tile.build.health = tile.build.maxHealth * prevPercent;
|
||||
if(unit != null && unit.isPlayer()) tile.build.lastAccessed = unit.getPlayer().name;
|
||||
|
||||
|
||||
Core.app.post(() -> Events.fire(new BlockBuildBeginEvent(tile, team, true)));
|
||||
Core.app.post(() -> Events.fire(new BlockBuildBeginEvent(tile, team, unit, true)));
|
||||
}
|
||||
|
||||
/** Places a ConstructBlock at this location. */
|
||||
@Remote(called = Loc.server)
|
||||
public static void beginPlace(Block result, Team team, int x, int y, int rotation){
|
||||
public static void beginPlace(@Nullable Unit unit, Block result, Team team, int x, int y, int rotation){
|
||||
if(!validPlace(result, team, x, y, rotation)){
|
||||
return;
|
||||
}
|
||||
@@ -57,6 +57,15 @@ public class Build{
|
||||
//just in case
|
||||
if(tile == null) return;
|
||||
|
||||
//auto-rotate the block to the correct orientation and bail out
|
||||
if(tile.team() == team && tile.block == result && tile.build != null){
|
||||
if(unit != null && unit.isPlayer()) tile.build.lastAccessed = unit.getPlayer().name;
|
||||
tile.build.rotation = Mathf.mod(rotation, 4);
|
||||
tile.build.updateProximity();
|
||||
tile.build.noSleep();
|
||||
return;
|
||||
}
|
||||
|
||||
Block previous = tile.block();
|
||||
Block sub = ConstructBlock.get(result.size);
|
||||
Seq<Building> prevBuild = new Seq<>(9);
|
||||
@@ -76,10 +85,11 @@ public class Build{
|
||||
|
||||
build.setConstruct(previous.size == sub.size ? previous : Blocks.air, result);
|
||||
build.prevBuild = prevBuild;
|
||||
if(unit != null && unit.isPlayer()) build.lastAccessed = unit.getPlayer().name;
|
||||
|
||||
result.placeBegan(tile, previous);
|
||||
|
||||
Core.app.post(() -> Events.fire(new BlockBuildBeginEvent(tile, team, false)));
|
||||
Core.app.post(() -> Events.fire(new BlockBuildBeginEvent(tile, team, unit, false)));
|
||||
}
|
||||
|
||||
/** Returns whether a tile can be placed at this location by this team. */
|
||||
|
||||
@@ -4,7 +4,7 @@ import arc.graphics.g2d.*;
|
||||
import arc.math.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
/**A type of floor that is overlaid on top of over floors.*/
|
||||
/**A type of floor that is overlaid on top of other floors.*/
|
||||
public class OverlayFloor extends Floor{
|
||||
|
||||
public OverlayFloor(String name){
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
package mindustry.world.blocks.units;
|
||||
|
||||
import mindustry.gen.*;
|
||||
import mindustry.world.*;
|
||||
|
||||
public class ControlCenter extends Block{
|
||||
|
||||
public ControlCenter(String name){
|
||||
super(name);
|
||||
update = true;
|
||||
}
|
||||
|
||||
public class ControlCenterBuild extends Building{
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user