Merge branch 'master' of https://github.com/Anuken/Mindustry into 7.0-features

 Conflicts:
	core/src/mindustry/mod/ClassMap.java
This commit is contained in:
Anuken
2021-07-04 09:52:57 -04:00
34 changed files with 168 additions and 135 deletions

View File

@@ -47,7 +47,8 @@ jobs:
git clone --depth=1 --branch=master https://github.com/Anuken/MindustryBuilds ../MindustryBuilds git clone --depth=1 --branch=master https://github.com/Anuken/MindustryBuilds ../MindustryBuilds
cd ../MindustryBuilds cd ../MindustryBuilds
echo "Updating version to ${RELEASE_VERSION:1}" echo "Updating version to ${RELEASE_VERSION:1}"
echo versionName=7-fdroid-${RELEASE_VERSION:1}$'\n'versionCode=${GITHUB_RUN_NUMBER} > version_fdroid.txt BNUM=$(($GITHUB_RUN_NUMBER + 1000))
echo versionName=7-fdroid-${RELEASE_VERSION:1}$'\n'versionCode=${BNUM} > version_fdroid.txt
git add . git add .
git commit -m "Updating to build ${RELEASE_VERSION:1}" git commit -m "Updating to build ${RELEASE_VERSION:1}"
git push https://Anuken:${{ secrets.API_TOKEN_GITHUB }}@github.com/Anuken/MindustryBuilds git push https://Anuken:${{ secrets.API_TOKEN_GITHUB }}@github.com/Anuken/MindustryBuilds

View File

@@ -501,9 +501,11 @@ task deployAll{
dependsOn "desktop:packrWindows64" dependsOn "desktop:packrWindows64"
dependsOn "desktop:packrWindows32" dependsOn "desktop:packrWindows32"
dependsOn "desktop:packrMacOS" dependsOn "desktop:packrMacOS"
if(versionModifier != "steam"){
dependsOn "server:deploy" dependsOn "server:deploy"
dependsOn "android:deploy" dependsOn "android:deploy"
} }
}
task resolveDependencies{ task resolveDependencies{
doLast{ doLast{

View File

@@ -806,6 +806,7 @@ bullet.reload = [stat]{0}[lightgray]x fire rate
unit.blocks = blocks unit.blocks = blocks
unit.blockssquared = blocks² unit.blockssquared = blocks²
unit.powersecond = power units/second unit.powersecond = power units/second
unit.tilessecond = tiles/second
unit.liquidsecond = liquid units/second unit.liquidsecond = liquid units/second
unit.itemssecond = items/second unit.itemssecond = items/second
unit.liquidunits = liquid units unit.liquidunits = liquid units

View File

@@ -1591,6 +1591,8 @@ lst.sensor = Mengambil data dari bangunan atau unit.
lst.set = Menentukan sebuah variabel. lst.set = Menentukan sebuah variabel.
lst.operation = Melakukan operasi pada 1-2 variabel. lst.operation = Melakukan operasi pada 1-2 variabel.
lst.end = Loncati ke awal dari tumpukan perintah. lst.end = Loncati ke awal dari tumpukan perintah.
lst.wait = Memberi jeda dalam detik yang ditentukan.
lst.lookup = Mencari tipe barang/cairan/unit/blok dengan ID.\nJumlah hitungan dari setiap tipe dapat dilihat dengan:\n[accent]@unitCount[] / [accent]@itemCount[] / [accent]@liquidCount[] / [accent]@blockCount[]
lst.jump = Loncati secara bersyarat ke pernyataan berikutnya. lst.jump = Loncati secara bersyarat ke pernyataan berikutnya.
lst.unitbind = Menautkan ke unit jenis berikutnya, dan menyimpannya di [accent]@unit[]. lst.unitbind = Menautkan ke unit jenis berikutnya, dan menyimpannya di [accent]@unit[].
lst.unitcontrol = Mengendalikan unit yang saat ini dihubungkan. lst.unitcontrol = Mengendalikan unit yang saat ini dihubungkan.

View File

@@ -460,6 +460,7 @@ toolmode.drawteams = Takım Çiz
toolmode.drawteams.description = Bloklar yerine takımları çizer.. toolmode.drawteams.description = Bloklar yerine takımları çizer..
filters.empty = [lightgray]Hiç filtre yok! Aşağıdaki butonla bir adet ekleyin. filters.empty = [lightgray]Hiç filtre yok! Aşağıdaki butonla bir adet ekleyin.
filter.distort = Çarpıt filter.distort = Çarpıt
filter.noise = Gürültü filter.noise = Gürültü
filter.enemyspawn = Düşman Doğma Alanı Seçimi filter.enemyspawn = Düşman Doğma Alanı Seçimi
@@ -476,6 +477,7 @@ filter.clear = Temizle
filter.option.ignore = Yoksay filter.option.ignore = Yoksay
filter.scatter = Saç filter.scatter = Saç
filter.terrain = Arazi filter.terrain = Arazi
filter.option.scale = Ölçek filter.option.scale = Ölçek
filter.option.chance = Şans filter.option.chance = Şans
filter.option.mag = Genlik filter.option.mag = Genlik
@@ -490,6 +492,7 @@ filter.option.block = Blok
filter.option.floor = Zemin filter.option.floor = Zemin
filter.option.flooronto = Hedef Zemin filter.option.flooronto = Hedef Zemin
filter.option.target = Target filter.option.target = Target
filter.option.replacement = Değiştirme
filter.option.wall = Duvar filter.option.wall = Duvar
filter.option.ore = Maden filter.option.ore = Maden
filter.option.floor2 = İkincil Duvar filter.option.floor2 = İkincil Duvar
@@ -675,6 +678,7 @@ unit.nobuild = [scarlet]Birlik inşa edemiyor
lastaccessed = [lightgray]Son Erişme: {0} lastaccessed = [lightgray]Son Erişme: {0}
block.unknown = [lightgray]??? block.unknown = [lightgray]???
stat.showinmap = <görüntülenecek haritayı yükle>
stat.description = Amaç stat.description = Amaç
stat.input = Giriş stat.input = Giriş
stat.output = Çıkış stat.output = Çıkış
@@ -991,6 +995,7 @@ rules.waves = Dalgalar
rules.attack = Saldırı Modu rules.attack = Saldırı Modu
rules.buildai = Yapay Zeka İnşası rules.buildai = Yapay Zeka İnşası
rules.corecapture = Yıkımca Çekirdeği Elegeçir rules.corecapture = Yıkımca Çekirdeği Elegeçir
rules.polygoncoreprotection = Çokgenli Çekirdek Koruması
rules.enemyCheat = Sonsuz AI (Kırmızı Takım) Kaynakları rules.enemyCheat = Sonsuz AI (Kırmızı Takım) Kaynakları
rules.blockhealthmultiplier = Blok Canı Çarpanı rules.blockhealthmultiplier = Blok Canı Çarpanı
rules.blockdamagemultiplier = Blok Hasarı Çarpanı rules.blockdamagemultiplier = Blok Hasarı Çarpanı
@@ -1161,7 +1166,8 @@ block.spore-cluster.name = Spor Kümesi
block.metal-floor.name = Metal Zemin 1 block.metal-floor.name = Metal Zemin 1
block.metal-floor-2.name = Metal Zemin 2 block.metal-floor-2.name = Metal Zemin 2
block.metal-floor-3.name = Metal Zemin 3 block.metal-floor-3.name = Metal Zemin 3
block.metal-floor-5.name = Metal Zemin 4 block.metal-floor-4.name = Metal Zemin 4
block.metal-floor-5.name = Metal Zemin 5
block.metal-floor-damaged.name = Hasarlı Metal Zemin block.metal-floor-damaged.name = Hasarlı Metal Zemin
block.dark-panel-1.name = Kara Panel 1 block.dark-panel-1.name = Kara Panel 1
block.dark-panel-2.name = Kara Panel 2 block.dark-panel-2.name = Kara Panel 2

View File

@@ -155,6 +155,7 @@ const BlockBuildBeginEvent = Packages.mindustry.game.EventType.BlockBuildBeginEv
const ResearchEvent = Packages.mindustry.game.EventType.ResearchEvent const ResearchEvent = Packages.mindustry.game.EventType.ResearchEvent
const UnlockEvent = Packages.mindustry.game.EventType.UnlockEvent const UnlockEvent = Packages.mindustry.game.EventType.UnlockEvent
const StateChangeEvent = Packages.mindustry.game.EventType.StateChangeEvent const StateChangeEvent = Packages.mindustry.game.EventType.StateChangeEvent
const CoreChangeEvent = Packages.mindustry.game.EventType.CoreChangeEvent
const TileChangeEvent = Packages.mindustry.game.EventType.TileChangeEvent const TileChangeEvent = Packages.mindustry.game.EventType.TileChangeEvent
const TilePreChangeEvent = Packages.mindustry.game.EventType.TilePreChangeEvent const TilePreChangeEvent = Packages.mindustry.game.EventType.TilePreChangeEvent
const GameOverEvent = Packages.mindustry.game.EventType.GameOverEvent const GameOverEvent = Packages.mindustry.game.EventType.GameOverEvent
@@ -166,6 +167,7 @@ const DepositEvent = Packages.mindustry.game.EventType.DepositEvent
const WithdrawEvent = Packages.mindustry.game.EventType.WithdrawEvent const WithdrawEvent = Packages.mindustry.game.EventType.WithdrawEvent
const SectorCaptureEvent = Packages.mindustry.game.EventType.SectorCaptureEvent const SectorCaptureEvent = Packages.mindustry.game.EventType.SectorCaptureEvent
const PlayerChatEvent = Packages.mindustry.game.EventType.PlayerChatEvent const PlayerChatEvent = Packages.mindustry.game.EventType.PlayerChatEvent
const MenuOptionChooseEvent = Packages.mindustry.game.EventType.MenuOptionChooseEvent
const ClientPreConnectEvent = Packages.mindustry.game.EventType.ClientPreConnectEvent const ClientPreConnectEvent = Packages.mindustry.game.EventType.ClientPreConnectEvent
const CommandIssueEvent = Packages.mindustry.game.EventType.CommandIssueEvent const CommandIssueEvent = Packages.mindustry.game.EventType.CommandIssueEvent
const SchematicCreateEvent = Packages.mindustry.game.EventType.SchematicCreateEvent const SchematicCreateEvent = Packages.mindustry.game.EventType.SchematicCreateEvent

View File

@@ -285,7 +285,7 @@ public class BlockIndexer{
for(int i = 0; i < activeTeams.size; i++){ for(int i = 0; i < activeTeams.size; i++){
Team enemy = activeTeams.items[i]; Team enemy = activeTeams.items[i];
if(enemy == team || team == Team.derelict) continue; if(enemy == team || (team == Team.derelict && !state.rules.coreCapture)) continue;
Building entity = indexer.findTile(enemy, x, y, range, pred, true); Building entity = indexer.findTile(enemy, x, y, range, pred, true);
if(entity != null){ if(entity != null){
@@ -360,7 +360,7 @@ public class BlockIndexer{
private void process(Tile tile){ private void process(Tile tile){
var team = tile.team(); var team = tile.team();
//only process entity changes with centered tiles //only process entity changes with centered tiles
if(tile.isCenter() && team != Team.derelict){ if(tile.isCenter() && tile.build != null){
var data = team.data(); var data = team.data();
if(tile.block().flags.size() > 0 && tile.isCenter()){ if(tile.block().flags.size() > 0 && tile.isCenter()){
TileArray[] map = getFlagged(team); TileArray[] map = getFlagged(team);

View File

@@ -119,9 +119,11 @@ public class Pathfinder implements Runnable{
} }
} }
int tid = tile.getTeamID();
return PathTile.get( return PathTile.get(
tile.build == null || !solid || tile.block() instanceof CoreBlock ? 0 : Math.min((int)(tile.build.health / 40), 80), tile.build == null || !solid || tile.block() instanceof CoreBlock ? 0 : Math.min((int)(tile.build.health / 40), 80),
tile.getTeamID(), tid == 0 && tile.build != null && state.rules.coreCapture ? 255 : tid, //use teamid = 255 when core capture is enabled to mark out derelict structures
solid, solid,
tile.floor().isLiquid, tile.floor().isLiquid,
tile.staticDarkness() >= 2 || (tile.floor().solid && tile.block() == Blocks.air), tile.staticDarkness() >= 2 || (tile.floor().solid && tile.block() == Blocks.air),

View File

@@ -104,7 +104,7 @@ public class LogicAI extends AIController{
//look where moving if there's nothing to aim at //look where moving if there's nothing to aim at
if(!shoot){ if(!shoot){
unit.lookAt(unit.prefRotation()); unit.lookAt(unit.prefRotation());
}else if(unit.hasWeapons() && unit.mounts.length > 0){ //if there is, look at the object }else if(unit.hasWeapons() && unit.mounts.length > 0 && !unit.mounts[0].weapon.ignoreRotation){ //if there is, look at the object
unit.lookAt(unit.mounts[0].aimX, unit.mounts[0].aimY); unit.lookAt(unit.mounts[0].aimX, unit.mounts[0].aimY);
} }
} }

View File

@@ -2147,25 +2147,25 @@ public class Blocks implements ContentList{
}}; }};
repairPoint = new RepairPoint("repair-point"){{ repairPoint = new RepairPoint("repair-point"){{
requirements(Category.units, with(Items.lead, 25, Items.copper, 25, Items.silicon, 20)); requirements(Category.units, with(Items.lead, 30, Items.copper, 30, Items.silicon, 20));
repairSpeed = 0.5f; repairSpeed = 0.45f;
repairRadius = 65f; repairRadius = 60f;
beamWidth = 0.73f; beamWidth = 0.73f;
powerUse = 1f; powerUse = 1f;
pulseRadius = 5f; pulseRadius = 5f;
}}; }};
repairTurret = new RepairPoint("repair-turret"){{ repairTurret = new RepairPoint("repair-turret"){{
requirements(Category.units, with(Items.silicon, 90, Items.thorium, 80, Items.plastanium, 80)); requirements(Category.units, with(Items.silicon, 90, Items.thorium, 80, Items.plastanium, 60));
size = 2; size = 2;
length = 6f; length = 6f;
repairSpeed = 3.25f; repairSpeed = 3f;
repairRadius = 140f; repairRadius = 145f;
powerUse = 5f; powerUse = 5f;
beamWidth = 1.1f; beamWidth = 1.1f;
pulseRadius = 6.1f; pulseRadius = 6.1f;
coolantUse = 0.16f; coolantUse = 0.16f;
coolantMultiplier = 1.5f; coolantMultiplier = 1.6f;
acceptCoolant = true; acceptCoolant = true;
}}; }};

View File

@@ -87,7 +87,7 @@ public class UnitTypes implements ContentList{
mace = new UnitType("mace"){{ mace = new UnitType("mace"){{
speed = 0.45f; speed = 0.45f;
hitSize = 10f; hitSize = 10f;
health = 530; health = 540;
armor = 4f; armor = 4f;
immunities.add(StatusEffects.burning); immunities.add(StatusEffects.burning);
@@ -96,7 +96,7 @@ public class UnitTypes implements ContentList{
top = false; top = false;
shootSound = Sounds.flame; shootSound = Sounds.flame;
shootY = 2f; shootY = 2f;
reload = 12f; reload = 11f;
recoil = 1f; recoil = 1f;
ejectEffect = Fx.none; ejectEffect = Fx.none;
bullet = new BulletType(4.1f, 32f){{ bullet = new BulletType(4.1f, 32f){{
@@ -1125,10 +1125,10 @@ public class UnitTypes implements ContentList{
BulletType fragBullet = new FlakBulletType(4f, 5){{ BulletType fragBullet = new FlakBulletType(4f, 5){{
shootEffect = Fx.shootBig; shootEffect = Fx.shootBig;
ammoMultiplier = 4f; ammoMultiplier = 4f;
splashDamage = 50f; splashDamage = 60f;
splashDamageRadius = 25f; splashDamageRadius = 25f;
collidesGround = true; collidesGround = true;
lifetime = 38f; lifetime = 47f;
status = StatusEffects.blasted; status = StatusEffects.blasted;
statusDuration = 60f; statusDuration = 60f;
@@ -1148,12 +1148,12 @@ public class UnitTypes implements ContentList{
rotate = true; rotate = true;
bullet = new LaserBulletType(){{ bullet = new LaserBulletType(){{
damage = 100f; damage = 110f;
sideAngle = 20f; sideAngle = 20f;
sideWidth = 1.5f; sideWidth = 1.5f;
sideLength = 80f; sideLength = 80f;
width = 25f; width = 25f;
length = 200f; length = 230f;
shootEffect = Fx.shockwave; shootEffect = Fx.shockwave;
colors = new Color[]{Color.valueOf("ec7458aa"), Color.valueOf("ff9c5a"), Color.white}; colors = new Color[]{Color.valueOf("ec7458aa"), Color.valueOf("ff9c5a"), Color.white};
}}; }};

View File

@@ -247,11 +247,11 @@ public class Logic implements ApplicationListener{
Events.fire(new GameOverEvent(state.rules.waveTeam)); Events.fire(new GameOverEvent(state.rules.waveTeam));
}else if(state.rules.attackMode){ }else if(state.rules.attackMode){
//count # of teams alive //count # of teams alive
int countAlive = state.teams.getActive().count(TeamData::hasCore); int countAlive = state.teams.getActive().count(t -> t.hasCore() && t.team != Team.derelict);
if((countAlive <= 1 || (!state.rules.pvp && state.rules.defaultTeam.core() == null)) && !state.gameOver){ if((countAlive <= 1 || (!state.rules.pvp && state.rules.defaultTeam.core() == null)) && !state.gameOver){
//find team that won //find team that won
TeamData left = state.teams.getActive().find(TeamData::hasCore); TeamData left = state.teams.getActive().find(t -> t.hasCore() && t.team != Team.derelict);
Events.fire(new GameOverEvent(left == null ? Team.derelict : left.team)); Events.fire(new GameOverEvent(left == null ? Team.derelict : left.team));
state.gameOver = true; state.gameOver = true;
} }

View File

@@ -114,22 +114,6 @@ public class Rules{
/** special tags for additional info. */ /** special tags for additional info. */
public StringMap tags = new StringMap(); public StringMap tags = new StringMap();
/** A team-specific ruleset. */
public static class TeamRule{
/** Whether to use building AI. */
public boolean ai;
/** TODO Tier of blocks/designs that the AI uses for building. [0, 1] */
public float aiTier = 1f;
/** Whether, when AI is enabled, ships should be spawned from the core. */
public boolean aiCoreSpawn = true;
/** If true, blocks don't require power or resources. */
public boolean cheat;
/** If true, resources are not consumed when building. */
public boolean infiniteResources;
/** If true, this team has infinite unit ammo. */
public boolean infiniteAmmo;
}
/** Copies this ruleset exactly. Not efficient at all, do not use often. */ /** Copies this ruleset exactly. Not efficient at all, do not use often. */
public Rules copy(){ public Rules copy(){
return JsonIO.copy(this); return JsonIO.copy(this);
@@ -150,6 +134,22 @@ public class Rules{
} }
} }
/** A team-specific ruleset. */
public static class TeamRule{
/** Whether to use building AI. */
public boolean ai;
/** TODO Tier of blocks/designs that the AI uses for building. [0, 1] */
public float aiTier = 1f;
/** Whether, when AI is enabled, ships should be spawned from the core. */
public boolean aiCoreSpawn = true;
/** If true, blocks don't require power or resources. */
public boolean cheat;
/** If true, resources are not consumed when building. */
public boolean infiniteResources;
/** If true, this team has infinite unit ammo. */
public boolean infiniteAmmo;
}
/** A simple map for storing TeamRules in an efficient way without hashing. */ /** A simple map for storing TeamRules in an efficient way without hashing. */
public static class TeamRules implements JsonSerializable{ public static class TeamRules implements JsonSerializable{
final TeamRule[] values = new TeamRule[Team.all.length]; final TeamRule[] values = new TeamRule[Team.all.length];

View File

@@ -97,7 +97,7 @@ public class Team implements Comparable<Team>{
} }
public boolean isEnemy(Team other){ public boolean isEnemy(Team other){
return state.teams.areEnemies(this, other); return this != other;
} }
public Seq<CoreBuild> cores(){ public Seq<CoreBuild> cores(){

View File

@@ -49,7 +49,7 @@ public class Teams{
public boolean eachEnemyCore(Team team, Boolf<CoreBuild> ret){ public boolean eachEnemyCore(Team team, Boolf<CoreBuild> ret){
for(TeamData data : active){ for(TeamData data : active){
if(areEnemies(team, data.team)){ if(team != data.team){
for(CoreBuild tile : data.cores){ for(CoreBuild tile : data.cores){
if(ret.get(tile)){ if(ret.get(tile)){
return true; return true;
@@ -62,7 +62,7 @@ public class Teams{
public void eachEnemyCore(Team team, Cons<Building> ret){ public void eachEnemyCore(Team team, Cons<Building> ret){
for(TeamData data : active){ for(TeamData data : active){
if(areEnemies(team, data.team)){ if(team != data.team){
for(Building tile : data.cores){ for(Building tile : data.cores){
ret.get(tile); ret.get(tile);
} }
@@ -91,11 +91,6 @@ public class Teams{
return get(team).active(); return get(team).active();
} }
/** Returns whether {@param other} is an enemy of {@param #team}. */
public boolean areEnemies(Team team, Team other){
return team != other;
}
public boolean canInteract(Team team, Team other){ public boolean canInteract(Team team, Team other){
return team == other || other == Team.derelict; return team == other || other == Team.derelict;
} }
@@ -216,7 +211,7 @@ public class Teams{
Seq<Team> enemies = new Seq<>(); Seq<Team> enemies = new Seq<>();
for(TeamData other : active){ for(TeamData other : active){
if(areEnemies(data.team, other.team)){ if(data.team != other.team){
enemies.add(other.team); enemies.add(other.team);
} }
} }

View File

@@ -339,7 +339,7 @@ public class BlockRenderer{
Draw.z(Layer.block); Draw.z(Layer.block);
} }
if(renderer.drawStatus && block.consumes.any()){ if(entity.team == player.team() && renderer.drawStatus && block.consumes.any()){
entity.drawStatus(); entity.drawStatus();
} }
} }

View File

@@ -1242,12 +1242,14 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
diagonal = !diagonal; diagonal = !diagonal;
} }
int endRotation = -1;
if(diagonal){ if(diagonal){
var start = world.build(startX, startY); var start = world.build(startX, startY);
var end = world.build(endX, endY); var end = world.build(endX, endY);
if(block != null && start instanceof ChainedBuilding && end instanceof ChainedBuilding if(block != null && start instanceof ChainedBuilding && end instanceof ChainedBuilding
&& block.canReplace(end.block) && block.canReplace(start.block)){ && block.canReplace(end.block) && block.canReplace(start.block)){
points = Placement.upgradeLine(startX, startY, endX, endY); points = Placement.upgradeLine(startX, startY, endX, endY);
endRotation = end.rotation;
}else{ }else{
points = Placement.pathfindLine(block != null && block.conveyorPlacement, startX, startY, endX, endY); points = Placement.pathfindLine(block != null && block.conveyorPlacement, startX, startY, endX, endY);
} }
@@ -1281,6 +1283,8 @@ public abstract class InputHandler implements InputProcessor, GestureListener{
int result = baseRotation; int result = baseRotation;
if(next != null){ if(next != null){
result = Tile.relativeTo(point.x, point.y, next.x, next.y); result = Tile.relativeTo(point.x, point.y, next.x, next.y);
}else if(endRotation != -1){
result = endRotation;
}else if(block.conveyorPlacement && i > 0){ }else if(block.conveyorPlacement && i > 0){
Point2 prev = points.get(i - 1); Point2 prev = points.get(i - 1);
result = Tile.relativeTo(prev.x, prev.y, point.x, point.y); result = Tile.relativeTo(prev.x, prev.y, point.x, point.y);

View File

@@ -167,6 +167,7 @@ public class ClassMap{
classes.put("StackConveyor", mindustry.world.blocks.distribution.StackConveyor.class); classes.put("StackConveyor", mindustry.world.blocks.distribution.StackConveyor.class);
classes.put("StackConveyorBuild", mindustry.world.blocks.distribution.StackConveyor.StackConveyorBuild.class); classes.put("StackConveyorBuild", mindustry.world.blocks.distribution.StackConveyor.StackConveyorBuild.class);
classes.put("AirBlock", mindustry.world.blocks.environment.AirBlock.class); classes.put("AirBlock", mindustry.world.blocks.environment.AirBlock.class);
classes.put("Bush", mindustry.world.blocks.environment.Bush.class);
classes.put("Cliff", mindustry.world.blocks.environment.Cliff.class); classes.put("Cliff", mindustry.world.blocks.environment.Cliff.class);
classes.put("DoubleOverlayFloor", mindustry.world.blocks.environment.DoubleOverlayFloor.class); classes.put("DoubleOverlayFloor", mindustry.world.blocks.environment.DoubleOverlayFloor.class);
classes.put("Floor", mindustry.world.blocks.environment.Floor.class); classes.put("Floor", mindustry.world.blocks.environment.Floor.class);
@@ -175,15 +176,19 @@ public class ClassMap{
classes.put("Prop", mindustry.world.blocks.environment.Prop.class); classes.put("Prop", mindustry.world.blocks.environment.Prop.class);
classes.put("ShallowLiquid", mindustry.world.blocks.environment.ShallowLiquid.class); classes.put("ShallowLiquid", mindustry.world.blocks.environment.ShallowLiquid.class);
classes.put("SpawnBlock", mindustry.world.blocks.environment.SpawnBlock.class); classes.put("SpawnBlock", mindustry.world.blocks.environment.SpawnBlock.class);
classes.put("StaticClusterWall", mindustry.world.blocks.environment.StaticClusterWall.class);
classes.put("StaticTree", mindustry.world.blocks.environment.StaticTree.class); classes.put("StaticTree", mindustry.world.blocks.environment.StaticTree.class);
classes.put("StaticWall", mindustry.world.blocks.environment.StaticWall.class); classes.put("StaticWall", mindustry.world.blocks.environment.StaticWall.class);
classes.put("TreeBlock", mindustry.world.blocks.environment.TreeBlock.class); classes.put("TreeBlock", mindustry.world.blocks.environment.TreeBlock.class);
classes.put("WallOreBlock", mindustry.world.blocks.environment.WallOreBlock.class); classes.put("WallOreBlock", mindustry.world.blocks.environment.WallOreBlock.class);
classes.put("WavingProp", mindustry.world.blocks.environment.WavingProp.class);
classes.put("WobbleProp", mindustry.world.blocks.environment.WobbleProp.class); classes.put("WobbleProp", mindustry.world.blocks.environment.WobbleProp.class);
classes.put("BlockLoader", BlockLoader.class); classes.put("BlockForge", mindustry.world.blocks.experimental.BlockForge.class);
classes.put("BlockLoaderBuild", BlockLoader.BlockLoaderBuild.class); classes.put("BlockForgeBuild", mindustry.world.blocks.experimental.BlockForge.BlockForgeBuild.class);
classes.put("BlockUnloader", BlockUnloader.class); classes.put("BlockLoader", mindustry.world.blocks.experimental.BlockLoader.class);
classes.put("BlockUnloaderBuild", BlockUnloader.BlockUnloaderBuild.class); classes.put("BlockLoaderBuild", mindustry.world.blocks.experimental.BlockLoader.BlockLoaderBuild.class);
classes.put("BlockUnloader", mindustry.world.blocks.experimental.BlockUnloader.class);
classes.put("BlockUnloaderBuild", mindustry.world.blocks.experimental.BlockUnloader.BlockUnloaderBuild.class);
classes.put("LegacyBlock", mindustry.world.blocks.legacy.LegacyBlock.class); classes.put("LegacyBlock", mindustry.world.blocks.legacy.LegacyBlock.class);
classes.put("LegacyMechPad", mindustry.world.blocks.legacy.LegacyMechPad.class); classes.put("LegacyMechPad", mindustry.world.blocks.legacy.LegacyMechPad.class);
classes.put("LegacyMechPadBuild", mindustry.world.blocks.legacy.LegacyMechPad.LegacyMechPadBuild.class); classes.put("LegacyMechPadBuild", mindustry.world.blocks.legacy.LegacyMechPad.LegacyMechPadBuild.class);
@@ -219,8 +224,12 @@ public class ClassMap{
classes.put("BallisticSiloBuild", mindustry.world.blocks.payloads.BallisticSilo.BallisticSiloBuild.class); classes.put("BallisticSiloBuild", mindustry.world.blocks.payloads.BallisticSilo.BallisticSiloBuild.class);
classes.put("BlockForge", mindustry.world.blocks.payloads.BlockForge.class); classes.put("BlockForge", mindustry.world.blocks.payloads.BlockForge.class);
classes.put("BlockForgeBuild", mindustry.world.blocks.payloads.BlockForge.BlockForgeBuild.class); classes.put("BlockForgeBuild", mindustry.world.blocks.payloads.BlockForge.BlockForgeBuild.class);
classes.put("BlockLoader", mindustry.world.blocks.payloads.BlockLoader.class);
classes.put("BlockLoaderBuild", mindustry.world.blocks.payloads.BlockLoader.BlockLoaderBuild.class);
classes.put("BlockProducer", mindustry.world.blocks.payloads.BlockProducer.class); classes.put("BlockProducer", mindustry.world.blocks.payloads.BlockProducer.class);
classes.put("BlockProducerBuild", mindustry.world.blocks.payloads.BlockProducer.BlockProducerBuild.class); classes.put("BlockProducerBuild", mindustry.world.blocks.payloads.BlockProducer.BlockProducerBuild.class);
classes.put("BlockUnloader", mindustry.world.blocks.payloads.BlockUnloader.class);
classes.put("BlockUnloaderBuild", mindustry.world.blocks.payloads.BlockUnloader.BlockUnloaderBuild.class);
classes.put("BuildPayload", mindustry.world.blocks.payloads.BuildPayload.class); classes.put("BuildPayload", mindustry.world.blocks.payloads.BuildPayload.class);
classes.put("NuclearWarhead", mindustry.world.blocks.payloads.NuclearWarhead.class); classes.put("NuclearWarhead", mindustry.world.blocks.payloads.NuclearWarhead.class);
classes.put("NuclearWarheadBuild", mindustry.world.blocks.payloads.NuclearWarhead.NuclearWarheadBuild.class); classes.put("NuclearWarheadBuild", mindustry.world.blocks.payloads.NuclearWarhead.NuclearWarheadBuild.class);
@@ -234,7 +243,7 @@ public class ClassMap{
classes.put("PayloadSource", mindustry.world.blocks.payloads.PayloadSource.class); classes.put("PayloadSource", mindustry.world.blocks.payloads.PayloadSource.class);
classes.put("PayloadSourceBuild", mindustry.world.blocks.payloads.PayloadSource.PayloadSourceBuild.class); classes.put("PayloadSourceBuild", mindustry.world.blocks.payloads.PayloadSource.PayloadSourceBuild.class);
classes.put("PayloadVoid", mindustry.world.blocks.payloads.PayloadVoid.class); classes.put("PayloadVoid", mindustry.world.blocks.payloads.PayloadVoid.class);
classes.put("BlockLoaderBuild", PayloadVoid.PayloadVoidBuild.class); classes.put("PayloadVoidBuild", mindustry.world.blocks.payloads.PayloadVoid.PayloadVoidBuild.class);
classes.put("UnitPayload", mindustry.world.blocks.payloads.UnitPayload.class); classes.put("UnitPayload", mindustry.world.blocks.payloads.UnitPayload.class);
classes.put("Battery", mindustry.world.blocks.power.Battery.class); classes.put("Battery", mindustry.world.blocks.power.Battery.class);
classes.put("BatteryBuild", mindustry.world.blocks.power.Battery.BatteryBuild.class); classes.put("BatteryBuild", mindustry.world.blocks.power.Battery.BatteryBuild.class);
@@ -242,6 +251,7 @@ public class ClassMap{
classes.put("BurnerGeneratorBuild", mindustry.world.blocks.power.BurnerGenerator.BurnerGeneratorBuild.class); classes.put("BurnerGeneratorBuild", mindustry.world.blocks.power.BurnerGenerator.BurnerGeneratorBuild.class);
classes.put("ConditionalConsumePower", mindustry.world.blocks.power.ConditionalConsumePower.class); classes.put("ConditionalConsumePower", mindustry.world.blocks.power.ConditionalConsumePower.class);
classes.put("DecayGenerator", mindustry.world.blocks.power.DecayGenerator.class); classes.put("DecayGenerator", mindustry.world.blocks.power.DecayGenerator.class);
classes.put("DynamicConsumePower", mindustry.world.blocks.power.DynamicConsumePower.class);
classes.put("ImpactReactor", mindustry.world.blocks.power.ImpactReactor.class); classes.put("ImpactReactor", mindustry.world.blocks.power.ImpactReactor.class);
classes.put("ImpactReactorBuild", mindustry.world.blocks.power.ImpactReactor.ImpactReactorBuild.class); classes.put("ImpactReactorBuild", mindustry.world.blocks.power.ImpactReactor.ImpactReactorBuild.class);
classes.put("ItemLiquidGenerator", mindustry.world.blocks.power.ItemLiquidGenerator.class); classes.put("ItemLiquidGenerator", mindustry.world.blocks.power.ItemLiquidGenerator.class);
@@ -330,6 +340,7 @@ public class ClassMap{
classes.put("DrawCells", mindustry.world.draw.DrawCells.class); classes.put("DrawCells", mindustry.world.draw.DrawCells.class);
classes.put("DrawCultivator", mindustry.world.draw.DrawCultivator.class); classes.put("DrawCultivator", mindustry.world.draw.DrawCultivator.class);
classes.put("DrawGlow", mindustry.world.draw.DrawGlow.class); classes.put("DrawGlow", mindustry.world.draw.DrawGlow.class);
classes.put("DrawLiquid", mindustry.world.draw.DrawLiquid.class);
classes.put("DrawMixer", mindustry.world.draw.DrawMixer.class); classes.put("DrawMixer", mindustry.world.draw.DrawMixer.class);
classes.put("DrawRotator", mindustry.world.draw.DrawRotator.class); classes.put("DrawRotator", mindustry.world.draw.DrawRotator.class);
classes.put("DrawSmelter", mindustry.world.draw.DrawSmelter.class); classes.put("DrawSmelter", mindustry.world.draw.DrawSmelter.class);

View File

@@ -391,15 +391,7 @@ public class ArcNetProvider implements NetProvider{
//no compression, copy over buffer //no compression, copy over buffer
if(compression == 0){ if(compression == 0){
buffer.position(0).limit(length); buffer.position(0).limit(length);
if(byteBuffer.hasArray()){
buffer.put(byteBuffer.array(), byteBuffer.position(), length); buffer.put(byteBuffer.array(), byteBuffer.position(), length);
}else{
byte[] readcopy = new byte[length];
int pos = byteBuffer.position();
byteBuffer.get(readcopy);
byteBuffer.position(pos);
buffer.put(readcopy);
}
buffer.position(0); buffer.position(0);
packet.read(reads.get(), length); packet.read(reads.get(), length);
//move read packets forward //move read packets forward

View File

@@ -147,26 +147,18 @@ public class CrashSender{
ex(() -> value.addChild("javaVersion", new JsonValue(System.getProperty("java.version")))); ex(() -> value.addChild("javaVersion", new JsonValue(System.getProperty("java.version"))));
ex(() -> value.addChild("javaArch", new JsonValue(System.getProperty("sun.arch.data.model")))); ex(() -> value.addChild("javaArch", new JsonValue(System.getProperty("sun.arch.data.model"))));
boolean[] sent = {false};
Log.info("Sending crash report."); Log.info("Sending crash report.");
//post to crash report URL, exit code indicates send success //post to crash report URL, exit code indicates send success
httpPost(Vars.crashReportURL, value.toJson(OutputType.json), r -> { new arc.Net().http(new HttpRequest().block(true).method(HttpMethod.POST).content(value.toJson(OutputType.json)).url(Vars.crashReportURL), r -> {
Log.info("Crash sent successfully."); Log.info("Crash sent successfully.");
sent[0] = true;
System.exit(1); System.exit(1);
}, t -> { }, t -> {
t.printStackTrace(); Log.info("Crash report not sent.");
sent[0] = true;
System.exit(-1); System.exit(-1);
}); });
//sleep until report is sent ret();
try{
while(!sent[0]){
Thread.sleep(30);
}
}catch(InterruptedException ignored){}
}catch(Throwable death){ }catch(Throwable death){
death.printStackTrace(); death.printStackTrace();
} }
@@ -178,10 +170,6 @@ public class CrashSender{
System.exit(1); System.exit(1);
} }
private static void httpPost(String url, String content, Cons<HttpResponse> success, Cons<Throwable> failure){
new NetJavaImpl().http(new HttpRequest().method(HttpMethod.POST).content(content).url(url), success, failure);
}
private static String parseException(Throwable e){ private static String parseException(Throwable e){
StringWriter sw = new StringWriter(); StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw); PrintWriter pw = new PrintWriter(sw);

View File

@@ -9,6 +9,7 @@ import arc.util.async.*;
import mindustry.gen.*; import mindustry.gen.*;
import mindustry.net.Packets.*; import mindustry.net.Packets.*;
import mindustry.net.Streamable.*; import mindustry.net.Streamable.*;
import net.jpountz.lz4.*;
import java.io.*; import java.io.*;
import java.nio.*; import java.nio.*;
@@ -33,7 +34,7 @@ public class Net{
private final ObjectMap<Class<?>, Cons> clientListeners = new ObjectMap<>(); private final ObjectMap<Class<?>, Cons> clientListeners = new ObjectMap<>();
private final ObjectMap<Class<?>, Cons2<NetConnection, Object>> serverListeners = new ObjectMap<>(); private final ObjectMap<Class<?>, Cons2<NetConnection, Object>> serverListeners = new ObjectMap<>();
private final IntMap<StreamBuilder> streams = new IntMap<>(); private final IntMap<StreamBuilder> streams = new IntMap<>();
private final ExecutorService pingExecutor = Threads.executor(Math.max(Runtime.getRuntime().availableProcessors(), 6)); private final ExecutorService pingExecutor = Threads.cachedExecutor();
private final NetProvider provider; private final NetProvider provider;
@@ -97,7 +98,7 @@ public class Net{
if(e instanceof BufferUnderflowException || e instanceof BufferOverflowException){ if(e instanceof BufferUnderflowException || e instanceof BufferOverflowException){
error = Core.bundle.get("error.io"); error = Core.bundle.get("error.io");
}else if(error.equals("mismatch") || (e instanceof IndexOutOfBoundsException && e.getStackTrace()[0].getClassName().contains("java.nio"))){ }else if(error.equals("mismatch") || e instanceof LZ4Exception || (e instanceof IndexOutOfBoundsException && e.getStackTrace()[0].getClassName().contains("java.nio"))){
error = Core.bundle.get("error.mismatch"); error = Core.bundle.get("error.mismatch");
}else if(error.contains("port out of range") || error.contains("invalid argument") || (error.contains("invalid") && error.contains("address")) || Strings.neatError(e).contains("address associated")){ }else if(error.contains("port out of range") || error.contains("invalid argument") || (error.contains("invalid") && error.contains("address")) || Strings.neatError(e).contains("address associated")){
error = Core.bundle.get("error.invalidaddress"); error = Core.bundle.get("error.invalidaddress");
@@ -325,13 +326,6 @@ public class Net{
pingExecutor.submit(() -> provider.pingHost(address, port, valid, failed)); pingExecutor.submit(() -> provider.pingHost(address, port, valid, failed));
} }
/**
* Pings a host in an new thread. If an error occurred, failed() should be called with the exception.
*/
public void pingHostThread(String address, int port, Cons<Host> valid, Cons<Exception> failed){
Threads.daemon(() -> provider.pingHost(address, port, valid, failed));
}
/** /**
* Whether the net is active, e.g. whether this is a multiplayer game. * Whether the net is active, e.g. whether this is a multiplayer game.
*/ */

View File

@@ -257,7 +257,7 @@ public class UnitType extends UnlockableContent{
stats.add(Stat.health, health); stats.add(Stat.health, health);
stats.add(Stat.armor, armor); stats.add(Stat.armor, armor);
stats.add(Stat.speed, speed); stats.add(Stat.speed, speed * 60f / tilesize, StatUnit.tilesSecond);
stats.add(Stat.size, hitSize / tilesize, StatUnit.blocksSquared); stats.add(Stat.size, hitSize / tilesize, StatUnit.blocksSquared);
stats.add(Stat.itemCapacity, itemCapacity); stats.add(Stat.itemCapacity, itemCapacity);
stats.add(Stat.range, (int)(maxRange / tilesize), StatUnit.blocks); stats.add(Stat.range, (int)(maxRange / tilesize), StatUnit.blocks);

View File

@@ -375,7 +375,7 @@ public class JoinDialog extends BaseDialog{
for(String address : group.addresses){ for(String address : group.addresses){
String resaddress = address.contains(":") ? address.split(":")[0] : address; String resaddress = address.contains(":") ? address.split(":")[0] : address;
int resport = address.contains(":") ? Strings.parseInt(address.split(":")[1]) : port; int resport = address.contains(":") ? Strings.parseInt(address.split(":")[1]) : port;
net.pingHostThread(resaddress, resport, res -> { net.pingHost(resaddress, resport, res -> {
if(refreshes != cur) return; if(refreshes != cur) return;
res.port = resport; res.port = resport;

View File

@@ -20,7 +20,7 @@ public class PayloadConveyor extends Block{
public @Load("@-top") TextureRegion topRegion; public @Load("@-top") TextureRegion topRegion;
public @Load("@-edge") TextureRegion edgeRegion; public @Load("@-edge") TextureRegion edgeRegion;
public Interp interp = Interp.pow5; public Interp interp = Interp.pow5;
public float payloadLimit = 2.9f; public float payloadLimit = 3f;
public PayloadConveyor(String name){ public PayloadConveyor(String name){
super(name); super(name);
@@ -75,7 +75,7 @@ public class PayloadConveyor extends Block{
@Override @Override
public boolean canControlSelect(Player player){ public boolean canControlSelect(Player player){
return this.item == null && !player.unit().spawnedByCore && player.unit().hitSize / tilesize <= payloadLimit && player.tileOn().build == this; return this.item == null && !player.unit().spawnedByCore && player.unit().hitSize / tilesize <= payloadLimit && player.tileOn() != null && player.tileOn().build == this;
} }
@Override @Override

View File

@@ -26,6 +26,7 @@ public interface Payload extends Position{
float size(); float size();
float x(); float x();
float y(); float y();
/** @return the items needed to make this payload; may be empty. */ /** @return the items needed to make this payload; may be empty. */
@@ -39,7 +40,7 @@ public interface Payload extends Position{
return false; return false;
} }
/** @return whether this payload fits in a given size. 2.5 is the max for a standard 3x3 conveyor. */ /** @return whether this payload fits in a given size. 3 is the max for a standard 3x3 conveyor. */
default boolean fits(float s){ default boolean fits(float s){
return size() / tilesize <= s; return size() / tilesize <= s;
} }

View File

@@ -30,6 +30,7 @@ public class Separator extends Block{
solid = true; solid = true;
hasItems = true; hasItems = true;
hasLiquids = true; hasLiquids = true;
sync = true;
} }
@Override @Override
@@ -45,6 +46,12 @@ public class Separator extends Block{
public float progress; public float progress;
public float totalProgress; public float totalProgress;
public float warmup; public float warmup;
public int seed;
@Override
public void created(){
seed = Mathf.randomSeed(tile.pos(), 0, Integer.MAX_VALUE - 1);
}
@Override @Override
public boolean shouldAmbientSound(){ public boolean shouldAmbientSound(){
@@ -91,7 +98,7 @@ public class Separator extends Block{
int sum = 0; int sum = 0;
for(ItemStack stack : results) sum += stack.amount; for(ItemStack stack : results) sum += stack.amount;
int i = Mathf.random(sum); int i = Mathf.randomSeed(seed++, 0, sum);
int count = 0; int count = 0;
Item item = null; Item item = null;
@@ -121,11 +128,19 @@ public class Separator extends Block{
return !consumes.itemFilters.get(item.id); return !consumes.itemFilters.get(item.id);
} }
//TODO write seed in 128 release, don't write it now for compatibility with 127.x
//@Override
//public byte version(){
// return 1;
//}
@Override @Override
public void write(Writes write){ public void write(Writes write){
super.write(write); super.write(write);
write.f(progress); write.f(progress);
write.f(warmup); write.f(warmup);
//TODO see above
//write.i(seed);
} }
@Override @Override
@@ -133,6 +148,8 @@ public class Separator extends Block{
super.read(read, revision); super.read(read, revision);
progress = read.f(); progress = read.f();
warmup = read.f(); warmup = read.f();
//TODO see above
//if(revision == 1) seed = read.i();
} }
} }
} }

View File

@@ -10,6 +10,7 @@ import java.util.*;
public enum StatUnit{ public enum StatUnit{
blocks, blocks,
blocksSquared, blocksSquared,
tilesSecond,
powerSecond, powerSecond,
liquidSecond, liquidSecond,
itemsSecond, itemsSecond,

View File

@@ -31,6 +31,7 @@ public class SNet implements SteamNetworkingCallback, SteamMatchmakingCallback,
final PacketSerializer serializer = new PacketSerializer(); final PacketSerializer serializer = new PacketSerializer();
final ByteBuffer writeBuffer = ByteBuffer.allocateDirect(16384); final ByteBuffer writeBuffer = ByteBuffer.allocateDirect(16384);
final ByteBuffer readBuffer = ByteBuffer.allocateDirect(16384); final ByteBuffer readBuffer = ByteBuffer.allocateDirect(16384);
final ByteBuffer readCopyBuffer = ByteBuffer.allocate(writeBuffer.capacity());
final CopyOnWriteArrayList<SteamConnection> connections = new CopyOnWriteArrayList<>(); final CopyOnWriteArrayList<SteamConnection> connections = new CopyOnWriteArrayList<>();
final IntMap<SteamConnection> steamConnections = new IntMap<>(); //maps steam ID -> valid net connection final IntMap<SteamConnection> steamConnections = new IntMap<>(); //maps steam ID -> valid net connection
@@ -51,10 +52,15 @@ public class SNet implements SteamNetworkingCallback, SteamMatchmakingCallback,
public void update(){ public void update(){
while((length = snet.isP2PPacketAvailable(0)) != 0){ while((length = snet.isP2PPacketAvailable(0)) != 0){
try{ try{
readBuffer.position(0); readBuffer.position(0).limit(readBuffer.capacity());
snet.readP2PPacket(from, readBuffer, 0); //lz4 chokes on direct buffers, so copy the bytes over
int len = snet.readP2PPacket(from, readBuffer, 0);
readBuffer.limit(len);
readCopyBuffer.position(0);
readCopyBuffer.put(readBuffer);
readCopyBuffer.position(0);
int fromID = from.getAccountID(); int fromID = from.getAccountID();
Object output = serializer.read(readBuffer); Object output = serializer.read(readCopyBuffer);
//it may be theoretically possible for this to be a framework message, if the packet is malicious or corrupted //it may be theoretically possible for this to be a framework message, if the packet is malicious or corrupted
if(!(output instanceof Packet)) return; if(!(output instanceof Packet)) return;
@@ -299,7 +305,7 @@ public class SNet implements SteamNetworkingCallback, SteamMatchmakingCallback,
@Override @Override
public void onLobbyMatchList(int matches){ public void onLobbyMatchList(int matches){
Log.info("found @ matches @", matches, lobbyDoneCallback); Log.info("found @ matches", matches);
if(lobbyDoneCallback != null){ if(lobbyDoneCallback != null){
Seq<Host> hosts = new Seq<>(); Seq<Host> hosts = new Seq<>();

View File

@@ -10,4 +10,4 @@ kapt.include.compile.classpath=false
kotlin.stdlib.default.dependency=false kotlin.stdlib.default.dependency=false
#needed for android compilation #needed for android compilation
android.useAndroidX=true android.useAndroidX=true
archash=1142cfc35b6671c6a2c5566632ff044a46527b82 archash=ca296ad37aeca186fcef3290bb8a6e9143bdd245

View File

@@ -595,43 +595,45 @@ public class ServerControl implements ApplicationListener{
netServer.admins.removeSubnetBan(arg[1]); netServer.admins.removeSubnetBan(arg[1]);
info("Unbanned @**", arg[1]); info("Unbanned @**", arg[1]);
}else{ }else{
err("Incorrect usage. You must provide add/remove as the second argument."); err("Incorrect usage. Provide add/remove as the second argument.");
} }
} }
}); });
handler.register("whitelisted", "List the entire whitelist.", arg -> { handler.register("whitelist", "[add/remove] [ID]", "Add/remove players from the whitelist using their ID.", arg -> {
if(netServer.admins.getWhitelisted().isEmpty()){ if(arg.length == 0){
Seq<PlayerInfo> whitelist = netServer.admins.getWhitelisted();
if(whitelist.isEmpty()){
info("No whitelisted players found."); info("No whitelisted players found.");
return; }else{
}
info("Whitelist:"); info("Whitelist:");
netServer.admins.getWhitelisted().each(p -> info("- @", p.lastName)); whitelist.each(p -> info("- Name: @ / UUID: @", p.lastName, p.id));
}); }
}else{
if(arg.length == 2){
PlayerInfo info = netServer.admins.getInfoOptional(arg[1]);
handler.register("whitelist-add", "<ID>", "Add a player to the whitelist by ID.", arg -> {
PlayerInfo info = netServer.admins.getInfoOptional(arg[0]);
if(info == null){ if(info == null){
err("Player ID not found. You must use the ID displayed when a player joins a server."); err("Player ID not found. You must use the ID displayed when a player joins a server.");
return; }else{
} if(arg[0].equals("add")){
netServer.admins.whitelist(arg[1]);
netServer.admins.whitelist(arg[0]);
info("Player '@' has been whitelisted.", info.lastName); info("Player '@' has been whitelisted.", info.lastName);
}); }else if(arg[0].equals("remove")){
netServer.admins.unwhitelist(arg[1]);
handler.register("whitelist-remove", "<ID>", "Remove a player to the whitelist by ID.", arg -> {
PlayerInfo info = netServer.admins.getInfoOptional(arg[0]);
if(info == null){
err("Player ID not found. You must use the ID displayed when a player joins a server.");
return;
}
netServer.admins.unwhitelist(arg[0]);
info("Player '@' has been un-whitelisted.", info.lastName); info("Player '@' has been un-whitelisted.", info.lastName);
}else{
err("Incorrect usage. Provide add/remove as the second argument.");
}
}
}else{
err("Incorrect usage. Provide an ID to add or remove.");
}
}
}); });
//TODO should be a config, not a separate command.
handler.register("shuffle", "[none/all/custom/builtin]", "Set map shuffling mode.", arg -> { handler.register("shuffle", "[none/all/custom/builtin]", "Set map shuffling mode.", arg -> {
if(arg.length == 0){ if(arg.length == 0){
info("Shuffle mode current set to '@'.", maps.getShuffleMode()); info("Shuffle mode current set to '@'.", maps.getShuffleMode());

View File

@@ -97,14 +97,22 @@
}, },
{ {
"name": "TSR", "name": "TSR",
"address": ["fifr4.quackhost.uk:20131"] "address": ["de15-3.falix.gg:27422"]
}, },
{ {
"name": "Sakura", "name": "Sakura",
"address": ["160.16.207.141", "160.16.207.141:21527", "160.16.207.141:31587"] "address": ["160.16.207.141", "160.16.207.141:21527", "160.16.207.141:31587", "160.16.207.141:26810"]
}, },
{ {
"name": "MeowLand", "name": "MeowLand",
"address": ["34.134.111.15"] "address": ["34.134.111.15"]
},
{
"name": "M-DE",
"address": ["mindustry.inc.li", "mindustry.inc.li:6568"]
},
{
"name": "Hungarian",
"address": ["magyarmindustry.tk"]
} }
] ]

View File

@@ -24,7 +24,7 @@
}, },
{ {
"name": "MeowLand", "name": "MeowLand",
"address": "34.134.111.15" "address": ["34.134.111.15", "fifr4.quackhost.uk:21013", "34.134.111.15:4000", "34.134.111.15:7000"]
}, },
{ {
"name": "Mindurka", "name": "Mindurka",

View File

@@ -14,9 +14,7 @@ public class GenericModTest{
static void grabMod(String url){ static void grabMod(String url){
//clear older mods //clear older mods
ApplicationTests.testDataFolder.deleteDirectory(); ApplicationTests.testDataFolder.deleteDirectory();
Core.net = new Net(); new Net().http(new HttpRequest().block(true).url(url).method(HttpMethod.GET), httpResponse -> {
Core.net.setBlock(true);
Core.net.http(new HttpRequest().url(url).method(HttpMethod.GET), httpResponse -> {
try{ try{
ApplicationTests.testDataFolder.child("mods").child("test_mod." + (url.endsWith("jar") ? "jar" : "zip")).writeBytes(Streams.copyBytes(httpResponse.getResultAsStream())); ApplicationTests.testDataFolder.child("mods").child("test_mod." + (url.endsWith("jar") ? "jar" : "zip")).writeBytes(Streams.copyBytes(httpResponse.getResultAsStream()));
}catch(IOException e){ }catch(IOException e){

View File

@@ -1,6 +1,7 @@
package mindustry.tools; package mindustry.tools;
import arc.*; import arc.*;
import arc.Net.*;
import arc.files.*; import arc.files.*;
import arc.util.*; import arc.util.*;
import arc.util.io.*; import arc.util.io.*;
@@ -18,7 +19,6 @@ public class FontGenerator{
//E000 to F8FF //E000 to F8FF
public static void main(String[] args){ public static void main(String[] args){
Net net = Core.net = new Net(); Net net = Core.net = new Net();
net.setBlock(true);
Fi folder = Fi.get("core/assets-raw/fontgen/out/"); Fi folder = Fi.get("core/assets-raw/fontgen/out/");
folder.mkdirs(); folder.mkdirs();
@@ -29,7 +29,7 @@ public class FontGenerator{
Log.info("Zip..."); Log.info("Zip...");
String session = folder.child("session").readString(); String session = folder.child("session").readString();
net.httpGet("https://fontello.com/" + session + "/get", result -> { net.http(new HttpRequest().method(HttpMethod.GET).url("https://fontello.com/" + session + "/get").block(true), result -> {
try{ try{
Streams.copy(result.getResultAsStream(), folder.child("font.zip").write()); Streams.copy(result.getResultAsStream(), folder.child("font.zip").write());
}catch(IOException e){ }catch(IOException e){