Merge branch 'master' of https://github.com/Anuken/Mindustry into markers-update
This commit is contained in:
@@ -214,7 +214,7 @@ public class CommandAI extends AIController{
|
||||
}
|
||||
|
||||
//TODO: should the unit stop when it finds a target?
|
||||
if(stance == UnitStance.patrol && target != null && unit.within(target, unit.type.range - 2f)){
|
||||
if(stance == UnitStance.patrol && target != null && unit.within(target, unit.type.range - 2f) && !unit.type.circleTarget){
|
||||
move = false;
|
||||
}
|
||||
|
||||
@@ -398,6 +398,8 @@ public class CommandAI extends AIController{
|
||||
|
||||
@Override
|
||||
public void commandPosition(Vec2 pos){
|
||||
if(pos == null) return;
|
||||
|
||||
commandPosition(pos, false);
|
||||
if(commandController != null){
|
||||
commandController.commandPosition(pos);
|
||||
@@ -405,8 +407,10 @@ public class CommandAI extends AIController{
|
||||
}
|
||||
|
||||
public void commandPosition(Vec2 pos, boolean stopWhenInRange){
|
||||
targetPos = pos;
|
||||
lastTargetPos = pos;
|
||||
if(pos == null) return;
|
||||
|
||||
//this is an allocation, but it's relatively rarely called anyway, and outside mutations must be prevented
|
||||
targetPos = lastTargetPos = pos.cpy();
|
||||
attackTarget = null;
|
||||
pathId = Vars.controlPath.nextTargetId();
|
||||
this.stopWhenInRange = stopWhenInRange;
|
||||
|
||||
@@ -570,7 +570,7 @@ public class Blocks{
|
||||
snowWall = new StaticWall("snow-wall");
|
||||
|
||||
duneWall = new StaticWall("dune-wall"){{
|
||||
basalt.asFloor().wall = darksandWater.asFloor().wall = darksandTaintedWater.asFloor().wall = this;
|
||||
hotrock.asFloor().wall = magmarock.asFloor().wall = basalt.asFloor().wall = darksandWater.asFloor().wall = darksandTaintedWater.asFloor().wall = this;
|
||||
attributes.set(Attribute.sand, 2f);
|
||||
}};
|
||||
|
||||
@@ -2408,7 +2408,7 @@ public class Blocks{
|
||||
largeSolarPanel = new SolarGenerator("solar-panel-large"){{
|
||||
requirements(Category.power, with(Items.lead, 80, Items.silicon, 110, Items.phaseFabric, 15));
|
||||
size = 3;
|
||||
powerProduction = 1.3f;
|
||||
powerProduction = 1.6f;
|
||||
}};
|
||||
|
||||
thoriumReactor = new NuclearReactor("thorium-reactor"){{
|
||||
|
||||
@@ -447,11 +447,11 @@ public class ErekirTechTree{
|
||||
|
||||
//nodeProduce(Liquids.gallium, () -> {});
|
||||
});
|
||||
});
|
||||
|
||||
nodeProduce(Items.surgeAlloy, () -> {
|
||||
nodeProduce(Items.phaseFabric, () -> {
|
||||
nodeProduce(Items.surgeAlloy, () -> {
|
||||
nodeProduce(Items.phaseFabric, () -> {
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -54,7 +54,7 @@ public class Liquids{
|
||||
capPuddles = false;
|
||||
spreadTarget = Liquids.water;
|
||||
moveThroughBlocks = true;
|
||||
incinerable = true;
|
||||
incinerable = false;
|
||||
blockReactive = false;
|
||||
canStayOn.addAll(water, oil, cryofluid);
|
||||
|
||||
|
||||
@@ -93,7 +93,8 @@ public class ShieldArcAbility extends Ability{
|
||||
paramField = this;
|
||||
paramPos.set(x, y).rotate(unit.rotation - 90f).add(unit);
|
||||
|
||||
Groups.bullet.intersect(unit.x - radius, unit.y - radius, radius * 2f, radius * 2f, shieldConsumer);
|
||||
float reach = radius + width / 2f;
|
||||
Groups.bullet.intersect(paramPos.x - reach, paramPos.y - reach, reach * 2f, reach * 2f, shieldConsumer);
|
||||
}else{
|
||||
widthScale = Mathf.lerpDelta(widthScale, 0f, 0.11f);
|
||||
}
|
||||
|
||||
@@ -160,6 +160,8 @@ public class BulletType extends Content implements Cloneable{
|
||||
|
||||
/** Bullet type that is created when this bullet expires. */
|
||||
public @Nullable BulletType fragBullet = null;
|
||||
/** If true, frag bullets are delayed to the next frame. Fixes obscure bugs with piercing bullet types spawning frags immediately and screwing up the Damage temporary variables. */
|
||||
public boolean delayFrags = false;
|
||||
/** Degree spread range of fragmentation bullets. */
|
||||
public float fragRandomSpread = 360f;
|
||||
/** Uniform spread between each frag bullet in degrees. */
|
||||
@@ -446,7 +448,11 @@ public class BulletType extends Content implements Cloneable{
|
||||
Effect.shake(hitShake, hitShake, b);
|
||||
|
||||
if(fragOnHit){
|
||||
createFrags(b, x, y);
|
||||
if(delayFrags && fragBullet != null && fragBullet.delayFrags){
|
||||
Core.app.post(() -> createFrags(b, x, y));
|
||||
}else{
|
||||
createFrags(b, x, y);
|
||||
}
|
||||
}
|
||||
createPuddles(b, x, y);
|
||||
createIncend(b, x, y);
|
||||
|
||||
@@ -38,6 +38,7 @@ public class LaserBulletType extends BulletType{
|
||||
hittable = false;
|
||||
absorbable = false;
|
||||
removeAfterPierce = false;
|
||||
delayFrags = true;
|
||||
}
|
||||
|
||||
public LaserBulletType(){
|
||||
|
||||
@@ -24,6 +24,7 @@ public class RailBulletType extends BulletType{
|
||||
collides = false;
|
||||
keepVelocity = false;
|
||||
lifetime = 1f;
|
||||
delayFrags = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -60,7 +61,7 @@ public class RailBulletType extends BulletType{
|
||||
super.init(b);
|
||||
|
||||
b.fdata = length;
|
||||
Damage.collideLine(b, b.team, b.type.hitEffect, b.x, b.y, b.rotation(), length, false, false);
|
||||
Damage.collideLine(b, b.team, b.type.hitEffect, b.x, b.y, b.rotation(), length, false, false, pierceCap);
|
||||
float resultLen = b.fdata;
|
||||
|
||||
Vec2 nor = Tmp.v1.trns(b.rotation(), 1f).nor();
|
||||
|
||||
@@ -1344,6 +1344,15 @@ abstract class BuildingComp implements Posc, Teamc, Healthc, Buildingc, Timerc,
|
||||
return block.itemCapacity;
|
||||
}
|
||||
|
||||
/** Called when a block begins (not finishes!) deconstruction. The building is still present at this point. */
|
||||
public void onDeconstructed(@Nullable Unit builder){
|
||||
//deposit non-incinerable liquid on ground
|
||||
if(liquids != null && liquids.currentAmount() > 0 && (!liquids.current().incinerable || block.deconstructDropAllLiquid)){
|
||||
float perCell = liquids.currentAmount() / (block.size * block.size) * 2f;
|
||||
tile.getLinkedTiles(other -> Puddles.deposit(other, liquids.current(), perCell));
|
||||
}
|
||||
}
|
||||
|
||||
/** Called when the block is destroyed. The tile is still intact at this stage. */
|
||||
public void onDestroyed(){
|
||||
float explosiveness = block.baseExplosiveness;
|
||||
|
||||
@@ -615,7 +615,9 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
||||
|
||||
@Remote(targets = Loc.both, called = Loc.both, forward = true)
|
||||
public static void tileConfig(@Nullable Player player, Building build, @Nullable Object value){
|
||||
if(build == null && net.server()) throw new ValidateException(player, "building is null");
|
||||
if(build == null) return;
|
||||
|
||||
if(net.server() && (!Units.canInteract(player, build) ||
|
||||
!netServer.admins.allowAction(player, ActionType.configure, build.tile, action -> action.config = value))){
|
||||
|
||||
@@ -1569,7 +1571,7 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
|
||||
consumed = true;
|
||||
if((!config.isShown() && build.shouldShowConfigure(player)) //if the config fragment is hidden, show
|
||||
//alternatively, the current selected block can 'agree' to switch config tiles
|
||||
|| (config.isShown() && config.getSelected().onConfigureBuildTapped(build))){
|
||||
|| (config.isShown() && config.getSelected().onConfigureBuildTapped(build) && build.shouldShowConfigure(player))){
|
||||
Sounds.click.at(build);
|
||||
config.showConfig(build);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import mindustry.game.Teams.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.logic.LogicFx.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.ui.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.environment.*;
|
||||
import mindustry.world.blocks.logic.*;
|
||||
@@ -945,12 +946,6 @@ public class LExecutor{
|
||||
//graphics on headless servers are useless.
|
||||
if(Vars.headless || exec.graphicsBuffer.size >= maxGraphicsBuffer) return;
|
||||
|
||||
int num1 = exec.numi(p1);
|
||||
|
||||
if(type == LogicDisplay.commandImage){
|
||||
num1 = exec.obj(p1) instanceof UnlockableContent u ? u.iconId : 0;
|
||||
}
|
||||
|
||||
//explicitly unpack colorPack, it's pre-processed here
|
||||
if(type == LogicDisplay.commandColorPack){
|
||||
double packed = exec.num(x);
|
||||
@@ -962,7 +957,63 @@ public class LExecutor{
|
||||
a = ((value & 0x000000ff));
|
||||
|
||||
exec.graphicsBuffer.add(DisplayCmd.get(LogicDisplay.commandColor, pack(r), pack(g), pack(b), pack(a), 0, 0));
|
||||
}else if(type == LogicDisplay.commandPrint){
|
||||
CharSequence str = exec.textBuffer;
|
||||
|
||||
if(str.length() > 0){
|
||||
var data = Fonts.logic.getData();
|
||||
int advance = (int)data.spaceXadvance, lineHeight = (int)data.lineHeight;
|
||||
|
||||
int xOffset, yOffset;
|
||||
int align = p1; //p1 is not a variable, it's a raw align value. what a massive hack
|
||||
|
||||
int maxWidth = 0, lines = 1, lineWidth = 0;
|
||||
for(int i = 0; i < str.length(); i++){
|
||||
char next = str.charAt(i);
|
||||
if(next == '\n'){
|
||||
maxWidth = Math.max(maxWidth, lineWidth);
|
||||
lineWidth = 0;
|
||||
lines ++;
|
||||
}else{
|
||||
lineWidth ++;
|
||||
}
|
||||
}
|
||||
maxWidth = Math.max(maxWidth, lineWidth);
|
||||
|
||||
float
|
||||
width = maxWidth * advance,
|
||||
height = lines * lineHeight,
|
||||
ha = ((Align.isLeft(align) ? -1f : 0f) + 1f + (Align.isRight(align) ? 1f : 0f))/2f,
|
||||
va = ((Align.isBottom(align) ? -1f : 0f) + 1f + (Align.isTop(align) ? 1f : 0f))/2f;
|
||||
|
||||
xOffset = -(int)(width * ha);
|
||||
yOffset = -(int)(height * va) + (lines - 1) * lineHeight;
|
||||
|
||||
|
||||
int curX = exec.numi(x), curY = exec.numi(y);
|
||||
for(int i = 0; i < str.length(); i++){
|
||||
char next = str.charAt(i);
|
||||
if(next == '\n'){
|
||||
//move Y down when newline is encountered
|
||||
curY -= lineHeight;
|
||||
curX = exec.numi(x); //reset
|
||||
continue;
|
||||
}
|
||||
if(Fonts.logic.getData().hasGlyph(next)){
|
||||
exec.graphicsBuffer.add(DisplayCmd.get(LogicDisplay.commandPrint, packSign(curX + xOffset), packSign(curY + yOffset), next, 0, 0, 0));
|
||||
}
|
||||
curX += advance;
|
||||
}
|
||||
|
||||
exec.textBuffer.setLength(0);
|
||||
}
|
||||
}else{
|
||||
int num1 = exec.numi(p1);
|
||||
|
||||
if(type == LogicDisplay.commandImage){
|
||||
num1 = exec.obj(p1) instanceof UnlockableContent u ? u.iconId : 0;
|
||||
}
|
||||
|
||||
//add graphics calls, cap graphics buffer size
|
||||
exec.graphicsBuffer.add(DisplayCmd.get(type, packSign(exec.numi(x)), packSign(exec.numi(y)), packSign(num1), packSign(exec.numi(p2)), packSign(exec.numi(p3)), packSign(exec.numi(p4))));
|
||||
}
|
||||
@@ -1459,7 +1510,8 @@ public class LExecutor{
|
||||
case ban -> {
|
||||
Object cont = exec.obj(value);
|
||||
if(cont instanceof Block b){
|
||||
state.rules.bannedBlocks.add(b);
|
||||
// Rebuild PlacementFragment if anything has changed
|
||||
if(state.rules.bannedBlocks.add(b) && !headless) ui.hudfrag.blockfrag.rebuild();
|
||||
}else if(cont instanceof UnitType u){
|
||||
state.rules.bannedUnits.add(u);
|
||||
}
|
||||
@@ -1467,7 +1519,7 @@ public class LExecutor{
|
||||
case unban -> {
|
||||
Object cont = exec.obj(value);
|
||||
if(cont instanceof Block b){
|
||||
state.rules.bannedBlocks.remove(b);
|
||||
if(state.rules.bannedBlocks.remove(b) && !headless) ui.hudfrag.blockfrag.rebuild();
|
||||
}else if(cont instanceof UnitType u){
|
||||
state.rules.bannedUnits.remove(u);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import arc.graphics.*;
|
||||
import arc.scene.style.*;
|
||||
import arc.scene.ui.*;
|
||||
import arc.scene.ui.layout.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.*;
|
||||
import mindustry.annotations.Annotations.*;
|
||||
@@ -121,6 +122,20 @@ public class LStatements{
|
||||
|
||||
@RegisterStatement("draw")
|
||||
public static class DrawStatement extends LStatement{
|
||||
static final String[] aligns = {"center", "top", "bottom", "left", "right", "topLeft", "topRight", "bottomLeft", "bottomRight"};
|
||||
//yes, boxing Integer is gross but this is easier to construct and Integers <128 don't allocate anyway
|
||||
static final ObjectMap<String, Integer> nameToAlign = ObjectMap.of(
|
||||
"center", Align.center,
|
||||
"top", Align.top,
|
||||
"bottom", Align.bottom,
|
||||
"left", Align.left,
|
||||
"right", Align.right,
|
||||
"topLeft", Align.topLeft,
|
||||
"topRight", Align.topRight,
|
||||
"bottomLeft", Align.bottomLeft,
|
||||
"bottomRight", Align.bottomRight
|
||||
);
|
||||
|
||||
public GraphicsType type = GraphicsType.clear;
|
||||
public String x = "0", y = "0", p1 = "0", p2 = "0", p3 = "0", p4 = "0";
|
||||
|
||||
@@ -147,6 +162,11 @@ public class LStatements{
|
||||
p2 = "32";
|
||||
p3 = "0";
|
||||
}
|
||||
|
||||
if(type == GraphicsType.print){
|
||||
p2 = "bottomLeft";
|
||||
}
|
||||
|
||||
rebuild(table);
|
||||
}, 2, cell -> cell.size(100, 50)));
|
||||
}, Styles.logict, () -> {}).size(90, 40).color(table.color).left().padLeft(2);
|
||||
@@ -225,14 +245,21 @@ public class LStatements{
|
||||
row(s);
|
||||
fields(s, "rotation", p3, v -> p3 = v);
|
||||
}
|
||||
//TODO
|
||||
/*
|
||||
case character -> {
|
||||
case print -> {
|
||||
fields(s, "x", x, v -> x = v);
|
||||
fields(s, "y", y, v -> y = v);
|
||||
|
||||
row(s);
|
||||
fields(s, "char", p1, v -> p1 = v);
|
||||
}*/
|
||||
|
||||
s.add("align ");
|
||||
|
||||
s.button(b -> {
|
||||
b.label(() -> nameToAlign.containsKey(p1) ? p1 : "bottomLeft");
|
||||
b.clicked(() -> showSelect(b, aligns, p1, t -> {
|
||||
p1 = t;
|
||||
}, 2, cell -> cell.size(165, 50)));
|
||||
}, Styles.logict, () -> {}).size(165, 40).color(s.color).left().padLeft(2);
|
||||
}
|
||||
}
|
||||
}).expand().left();
|
||||
}
|
||||
@@ -247,7 +274,8 @@ public class LStatements{
|
||||
|
||||
@Override
|
||||
public LInstruction build(LAssembler builder){
|
||||
return new DrawI((byte)type.ordinal(), 0, builder.var(x), builder.var(y), builder.var(p1), builder.var(p2), builder.var(p3), builder.var(p4));
|
||||
return new DrawI((byte)type.ordinal(), 0, builder.var(x), builder.var(y),
|
||||
type == GraphicsType.print ? nameToAlign.get(p1, Align.bottomLeft) : builder.var(p1), builder.var(p2), builder.var(p3), builder.var(p4));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -335,7 +335,7 @@ public abstract class BasicGenerator implements WorldGenerator{
|
||||
ore = tile.overlay();
|
||||
r.get(tile.x, tile.y);
|
||||
tile.setFloor(floor.asFloor());
|
||||
tile.setBlock(block);
|
||||
if(block != tile.block()) tile.setBlock(block);
|
||||
tile.setOverlay(ore);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import arc.func.*;
|
||||
import arc.math.*;
|
||||
import arc.net.*;
|
||||
import arc.net.FrameworkMessage.*;
|
||||
import arc.net.Server.*;
|
||||
import arc.net.dns.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
@@ -161,6 +162,11 @@ public class ArcNetProvider implements NetProvider{
|
||||
server.setConnectFilter(connectFilter);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable ServerConnectFilter getConnectFilter(){
|
||||
return server.getConnectFilter();
|
||||
}
|
||||
|
||||
private static boolean isLocal(InetAddress addr){
|
||||
if(addr.isAnyLocalAddress() || addr.isLoopbackAddress()) return true;
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package mindustry.net;
|
||||
import arc.*;
|
||||
import arc.func.*;
|
||||
import arc.net.*;
|
||||
import arc.net.Server.*;
|
||||
import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.game.EventType.*;
|
||||
@@ -325,6 +326,15 @@ public class Net{
|
||||
}
|
||||
}
|
||||
|
||||
/** Sets a connection filter by IP address. If the filter returns {@code false}, the connection will be closed. Server only. */
|
||||
public void setConnectFilter(@Nullable ServerConnectFilter filter){
|
||||
provider.setConnectFilter(filter);
|
||||
}
|
||||
|
||||
public @Nullable ServerConnectFilter getConnectFilter(){
|
||||
return provider.getConnectFilter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pings a host in a pooled thread. If an error occurred, failed() should be called with the exception.
|
||||
* If the port is the default mindustry port, SRV records are checked too.
|
||||
@@ -401,5 +411,9 @@ public class Net{
|
||||
|
||||
/** Sets a connection filter by IP address. If the filter returns {@code false}, the connection will be closed. */
|
||||
default void setConnectFilter(Server.ServerConnectFilter connectFilter){}
|
||||
|
||||
default @Nullable ServerConnectFilter getConnectFilter(){
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import mindustry.game.SectorInfo.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.defense.*;
|
||||
import mindustry.world.blocks.defense.Wall.*;
|
||||
import mindustry.world.blocks.defense.turrets.Turret.*;
|
||||
import mindustry.world.blocks.distribution.*;
|
||||
@@ -111,16 +110,10 @@ public class GameService{
|
||||
completeSerpulo.complete();
|
||||
}
|
||||
|
||||
if(mods.list().size > 0){
|
||||
if(mods != null && mods.list().size > 0){
|
||||
installMod.complete();
|
||||
}
|
||||
|
||||
Events.on(ClientLoadEvent.class, e -> {
|
||||
if(mods.list().size > 0){
|
||||
installMod.complete();
|
||||
}
|
||||
});
|
||||
|
||||
if(Core.bundle.get("yes").equals("router")){
|
||||
routerLanguage.complete();
|
||||
}
|
||||
@@ -231,8 +224,8 @@ public class GameService{
|
||||
}
|
||||
}
|
||||
|
||||
if(e.tile.block() instanceof MendProjector || e.tile.block() instanceof RegenProjector) buildMendProjector.complete();
|
||||
if(e.tile.block() instanceof OverdriveProjector) buildOverdriveProjector.complete();
|
||||
if(e.tile.block() == Blocks.mendProjector) buildMendProjector.complete();
|
||||
if(e.tile.block() == Blocks.overdriveProjector) buildOverdriveProjector.complete();
|
||||
|
||||
if(e.tile.block() == Blocks.waterExtractor){
|
||||
if(e.tile.getLinkedTiles(tmpTiles).contains(t -> t.floor().liquidDrop == Liquids.water)){
|
||||
@@ -459,7 +452,8 @@ public class GameService{
|
||||
//check unlocked stuff on load as well
|
||||
Events.on(ResearchEvent.class, e -> checkUnlocks.run());
|
||||
Events.on(UnlockEvent.class, e -> checkUnlocks.run());
|
||||
Events.on(ClientLoadEvent.class, e -> checkUnlocks.run());
|
||||
|
||||
checkUnlocks.run();
|
||||
|
||||
Events.on(WinEvent.class, e -> {
|
||||
if(state.rules.pvp){
|
||||
|
||||
@@ -35,7 +35,7 @@ public class Fonts{
|
||||
private static TextureRegion[] iconTable;
|
||||
private static int lastCid;
|
||||
|
||||
public static Font def, outline, icon, iconLarge, tech;
|
||||
public static Font def, outline, icon, iconLarge, tech, logic;
|
||||
|
||||
public static TextureRegion logicIcon(int id){
|
||||
return iconTable[id];
|
||||
@@ -71,11 +71,13 @@ public class Fonts{
|
||||
FreeTypeFontParameter param = fontParameter();
|
||||
|
||||
Core.assets.load("default", Font.class, new FreeTypeFontLoaderParameter(mainFont, param)).loaded = f -> Fonts.def = f;
|
||||
|
||||
Core.assets.load("icon", Font.class, new FreeTypeFontLoaderParameter("fonts/icon.ttf", new FreeTypeFontParameter(){{
|
||||
size = 30;
|
||||
incremental = true;
|
||||
characters = "\0";
|
||||
}})).loaded = f -> Fonts.icon = f;
|
||||
|
||||
Core.assets.load("iconLarge", Font.class, new FreeTypeFontLoaderParameter("fonts/icon.ttf", new FreeTypeFontParameter(){{
|
||||
size = 48;
|
||||
incremental = false;
|
||||
@@ -83,6 +85,14 @@ public class Fonts{
|
||||
borderWidth = 5f;
|
||||
borderColor = Color.darkGray;
|
||||
}})).loaded = f -> Fonts.iconLarge = f;
|
||||
|
||||
Core.assets.load("logic", Font.class, new FreeTypeFontLoaderParameter("fonts/logic.ttf", new FreeTypeFontParameter(){{
|
||||
size = 16;
|
||||
//generated all at once, it's fast enough anyway
|
||||
incremental = false;
|
||||
//ASCII only
|
||||
characters = "\0ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890\"!`?'.,;:()[]{}<>|/@\\^$€-%+=#_&~*";
|
||||
}})).loaded = f -> Fonts.logic = f;
|
||||
}
|
||||
|
||||
public static TextureRegion getLargeIcon(String name){
|
||||
|
||||
@@ -247,29 +247,12 @@ public class JoinDialog extends BaseDialog{
|
||||
void setupServer(Server server, Host host){
|
||||
server.lastHost = host;
|
||||
server.content.clear();
|
||||
buildServer(host, server.content);
|
||||
buildServer(host, server.content, false);
|
||||
}
|
||||
|
||||
void buildServer(Host host, Table content){
|
||||
void buildServer(Host host, Table content, boolean inner){
|
||||
content.top().left();
|
||||
String versionString;
|
||||
|
||||
if(host.version == -1){
|
||||
versionString = Core.bundle.format("server.version", Core.bundle.get("server.custombuild"), "");
|
||||
}else if(host.version == 0){
|
||||
versionString = Core.bundle.get("server.outdated");
|
||||
}else if(host.version < Version.build && Version.build != -1){
|
||||
versionString = Core.bundle.get("server.outdated") + "\n" +
|
||||
Core.bundle.format("server.version", host.version, "");
|
||||
}else if(host.version > Version.build && Version.build != -1){
|
||||
versionString = Core.bundle.get("server.outdated.client") + "\n" +
|
||||
Core.bundle.format("server.version", host.version, "");
|
||||
}else if(host.version == Version.build && Version.type.equals(host.versionType)){
|
||||
//not important
|
||||
versionString = "";
|
||||
}else{
|
||||
versionString = Core.bundle.format("server.version", host.version, host.versionType);
|
||||
}
|
||||
String versionString = getVersionString(host);
|
||||
|
||||
float twidth = targetWidth() - 40f;
|
||||
|
||||
@@ -277,12 +260,14 @@ public class JoinDialog extends BaseDialog{
|
||||
|
||||
Color color = Pal.gray;
|
||||
|
||||
content.table(Tex.whiteui, t -> {
|
||||
t.left();
|
||||
t.setColor(color);
|
||||
if(inner){
|
||||
content.table(Tex.whiteui, t -> {
|
||||
t.left();
|
||||
t.setColor(color);
|
||||
|
||||
t.add(host.name + " " + versionString).style(Styles.outlineLabel).padLeft(10f).width(twidth).left().ellipsis(true);
|
||||
}).growX().height(36f).row();
|
||||
t.add(host.name + " " + versionString).style(Styles.outlineLabel).padLeft(10f).width(twidth).left().ellipsis(true);
|
||||
}).growX().height(36f).row();
|
||||
}
|
||||
|
||||
content.table(Tex.whitePane, t -> {
|
||||
t.top().left();
|
||||
@@ -485,11 +470,16 @@ public class JoinDialog extends BaseDialog{
|
||||
|
||||
void addCommunityHost(Host host, Table container){
|
||||
global.background(null);
|
||||
String versionString = getVersionString(host);
|
||||
float w = targetWidth();
|
||||
|
||||
container.left().top();
|
||||
|
||||
container.button(b -> buildServer(host, b), style, () -> {
|
||||
Button[] button = {null};
|
||||
|
||||
button[0] = container.button(b -> {}, style, () -> {
|
||||
if(button[0].childrenPressed()) return;
|
||||
|
||||
Events.fire(new ClientPreConnectEvent(host));
|
||||
if(!Core.settings.getBool("server-disclaimer", false)){
|
||||
ui.showCustomConfirm("@warning", "@servers.disclaimer", "@ok", "@back", () -> {
|
||||
@@ -501,7 +491,28 @@ public class JoinDialog extends BaseDialog{
|
||||
}else{
|
||||
safeConnect(host.address, host.port, host.version);
|
||||
}
|
||||
}).width(w).padBottom(7).padRight(4f).top().left().growY().uniformY();
|
||||
}).width(w).padBottom(7).padRight(4f).top().left().growY().uniformY().get();
|
||||
|
||||
Table inner = new Table(Tex.whiteui);
|
||||
inner.setColor(Pal.gray);
|
||||
|
||||
button[0].clearChildren();
|
||||
button[0].add(inner).growX();
|
||||
|
||||
inner.add(host.name + " " + versionString).left().padLeft(10f).wrap().style(Styles.outlineLabel).growX();
|
||||
|
||||
inner.button(Icon.add, Styles.emptyi, () -> {
|
||||
Server server = new Server();
|
||||
server.setIP(host.address + ":" + host.port);
|
||||
servers.add(server);
|
||||
saveServers();
|
||||
setupRemote();
|
||||
refreshRemote();
|
||||
}).margin(3f).pad(8f).padRight(4f).top().right();
|
||||
|
||||
button[0].row();
|
||||
|
||||
buildServer(host, button[0].table(t -> {}).grow().get(), false);
|
||||
|
||||
if((container.getChildren().size) % columns() == 0){
|
||||
container.row();
|
||||
@@ -532,7 +543,7 @@ public class JoinDialog extends BaseDialog{
|
||||
local.row();
|
||||
}
|
||||
|
||||
local.button(b -> buildServer(host, b), style, () -> {
|
||||
local.button(b -> buildServer(host, b, true), style, () -> {
|
||||
Events.fire(new ClientPreConnectEvent(host));
|
||||
safeConnect(host.address, host.port, host.version);
|
||||
}).width(w).top().left().growY();
|
||||
@@ -641,6 +652,25 @@ public class JoinDialog extends BaseDialog{
|
||||
Core.settings.putJson("servers", Server.class, servers);
|
||||
}
|
||||
|
||||
private String getVersionString(Host host){
|
||||
if(host.version == -1){
|
||||
return Core.bundle.format("server.version", Core.bundle.get("server.custombuild"), "");
|
||||
}else if(host.version == 0){
|
||||
return Core.bundle.get("server.outdated");
|
||||
}else if(host.version < Version.build && Version.build != -1){
|
||||
return Core.bundle.get("server.outdated") + "\n" +
|
||||
Core.bundle.format("server.version", host.version, "");
|
||||
}else if(host.version > Version.build && Version.build != -1){
|
||||
return Core.bundle.get("server.outdated.client") + "\n" +
|
||||
Core.bundle.format("server.version", host.version, "");
|
||||
}else if(host.version == Version.build && Version.type.equals(host.versionType)){
|
||||
//not important
|
||||
return "";
|
||||
}else{
|
||||
return Core.bundle.format("server.version", host.version, host.versionType);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Server{
|
||||
public String ip;
|
||||
public int port;
|
||||
|
||||
@@ -113,7 +113,7 @@ public class PlacementFragment{
|
||||
return hover;
|
||||
}
|
||||
|
||||
void rebuild(){
|
||||
public void rebuild(){
|
||||
//category does not change on rebuild anymore, only on new world load
|
||||
Group group = toggler.parent;
|
||||
int index = toggler.getZIndex();
|
||||
|
||||
@@ -154,6 +154,8 @@ public class Block extends UnlockableContent implements Senseable{
|
||||
public boolean updateInUnits = true;
|
||||
/** if true, this block updates in payloads in units regardless of the experimental game rule */
|
||||
public boolean alwaysUpdateInUnits = false;
|
||||
/** if false, only incinerable liquids are dropped when deconstructing; otherwise, all liquids are dropped. */
|
||||
public boolean deconstructDropAllLiquid = false;
|
||||
/** Whether to use this block's color in the minimap. Only used for overlays. */
|
||||
public boolean useColor = true;
|
||||
/** item that drops from this block, used for drills */
|
||||
|
||||
@@ -47,7 +47,10 @@ public class Build{
|
||||
Block sub = ConstructBlock.get(previous.size);
|
||||
|
||||
Seq<Building> prevBuild = new Seq<>(1);
|
||||
if(tile.build != null) prevBuild.add(tile.build);
|
||||
if(tile.build != null){
|
||||
prevBuild.add(tile.build);
|
||||
tile.build.onDeconstructed(unit);
|
||||
}
|
||||
|
||||
tile.setBlock(sub, team, rotation);
|
||||
var build = (ConstructBuild)tile.build;
|
||||
|
||||
@@ -418,14 +418,23 @@ public class ItemBridge extends Block{
|
||||
checkAccept(source, world.tile(link));
|
||||
}
|
||||
|
||||
protected boolean checkAccept(Building source, Tile other){
|
||||
protected boolean checkAccept(Building source, Tile link){
|
||||
if(tile == null || linked(source)) return true;
|
||||
|
||||
if(linkValid(tile, other)){
|
||||
int rel = relativeTo(other);
|
||||
if(linkValid(tile, link)){
|
||||
int rel = relativeTo(link);
|
||||
var facing = Edges.getFacingEdge(source, this);
|
||||
int rel2 = facing == null ? -1 : relativeTo(facing);
|
||||
|
||||
//this is a bug, but it is kept for compatibility, see: https://github.com/Anuken/Mindustry/issues/9257#issuecomment-1801998747
|
||||
/*
|
||||
for(int j = 0; j < incoming.size; j++){
|
||||
int v = incoming.items[j];
|
||||
if(relativeTo(Point2.x(v), Point2.y(v)) == rel2){
|
||||
return false;
|
||||
}
|
||||
}*/
|
||||
|
||||
return rel != rel2;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,8 @@ public class LogicDisplay extends Block{
|
||||
commandLinePoly = 8,
|
||||
commandTriangle = 9,
|
||||
commandImage = 10,
|
||||
commandCharacter = 11;
|
||||
//note that this command actually only draws 1 character, unpacked in instruction
|
||||
commandPrint = 11;
|
||||
|
||||
public int maxSides = 25;
|
||||
|
||||
@@ -103,8 +104,14 @@ public class LogicDisplay extends Block{
|
||||
var icon = Fonts.logicIcon(p1);
|
||||
Draw.rect(Fonts.logicIcon(p1), x, y, p2, p2 / icon.ratio(), p3);
|
||||
}
|
||||
case commandCharacter -> {
|
||||
//TODO
|
||||
case commandPrint -> {
|
||||
var glyph = Fonts.logic.getData().getGlyph((char)p1);
|
||||
if(glyph != null){
|
||||
Tmp.tr1.set(Fonts.logic.getRegion().texture);
|
||||
Tmp.tr1.set(glyph.u, glyph.v2, glyph.u2, glyph.v);
|
||||
|
||||
Draw.rect(Tmp.tr1, x + Tmp.tr1.width/2f + glyph.xoffset, y + Tmp.tr1.height/2f + glyph.yoffset + Fonts.logic.getData().capHeight + Fonts.logic.getData().ascent, Tmp.tr1.width, Tmp.tr1.height);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -151,7 +158,8 @@ public class LogicDisplay extends Block{
|
||||
linePoly,
|
||||
triangle,
|
||||
image,
|
||||
;//character;
|
||||
//note that this command actually only draws 1 character, unpacked in instruction
|
||||
print;
|
||||
|
||||
public static final GraphicsType[] all = values();
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import arc.math.*;
|
||||
import arc.util.*;
|
||||
import arc.util.io.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.entities.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.graphics.*;
|
||||
import mindustry.logic.*;
|
||||
@@ -140,6 +141,16 @@ public class PayloadDeconstructor extends PayloadBlock{
|
||||
float shift = edelta() * deconstructSpeed / deconstructing.buildTime();
|
||||
float realShift = Math.min(shift, 1f - progress);
|
||||
|
||||
//if began deconstruction...
|
||||
if(progress == 0f && shift > 0f && deconstructing instanceof BuildPayload pay){
|
||||
var build = pay.build;
|
||||
//dump liquid on floor (does not respect block configuration with respect to dumping liquids on floor)
|
||||
if(build.liquids != null && build.liquids.currentAmount() > 0){
|
||||
float perCell = build.liquids.currentAmount() / (block.size * block.size) * 2f;
|
||||
tile.getLinkedTiles(other -> Puddles.deposit(other, build.liquids.current(), perCell));
|
||||
}
|
||||
}
|
||||
|
||||
progress += shift;
|
||||
time += edelta();
|
||||
|
||||
|
||||
@@ -122,9 +122,10 @@ public class BeamNode extends PowerBlock{
|
||||
|
||||
@Override
|
||||
public BlockStatus status(){
|
||||
if(Mathf.equal(power.status, 0f, 0.001f)) return BlockStatus.noInput;
|
||||
if(Mathf.equal(power.status, 1f, 0.001f)) return BlockStatus.active;
|
||||
return BlockStatus.noOutput;
|
||||
float balance = power.graph.getPowerBalance();
|
||||
if(balance > 0f) return BlockStatus.active;
|
||||
if(balance < 0f && power.graph.getLastPowerStored() > 0) return BlockStatus.noOutput;
|
||||
return BlockStatus.noInput;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -5,6 +5,7 @@ import arc.struct.*;
|
||||
import arc.util.*;
|
||||
import mindustry.content.*;
|
||||
import mindustry.gen.*;
|
||||
import mindustry.logic.*;
|
||||
import mindustry.type.*;
|
||||
import mindustry.world.*;
|
||||
import mindustry.world.blocks.storage.CoreBlock.*;
|
||||
@@ -100,6 +101,12 @@ public class StorageBlock extends Block{
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public double sense(LAccess sensor){
|
||||
if(sensor == LAccess.itemCapacity && linkedCore != null) return linkedCore.sense(sensor);
|
||||
return super.sense(sensor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void overwrote(Seq<Building> previous){
|
||||
//only add prev items when core is not linked
|
||||
|
||||
@@ -444,7 +444,7 @@ public class UnitAssembler extends PayloadBlock{
|
||||
|
||||
if(!net.client()){
|
||||
var unit = plan.unit.create(team);
|
||||
if(unit != null && unit.isCommandable()){
|
||||
if(unit != null && unit.isCommandable() && commandPos != null){
|
||||
unit.command().commandPosition(commandPos);
|
||||
}
|
||||
unit.set(spawn.x + Mathf.range(0.001f), spawn.y + Mathf.range(0.001f));
|
||||
|
||||
Reference in New Issue
Block a user