# Conflicts:

#	core/src/mindustry/mod/ClassMap.java
This commit is contained in:
Anuken 2021-06-15 19:29:12 -04:00
parent ac111677c0
commit eed91eaaa0
72 changed files with 820 additions and 704 deletions

View File

@ -6,15 +6,15 @@ on:
- 'v*'
jobs:
buildJava14:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 14
- name: Set up JDK 16
uses: actions/setup-java@v1
with:
java-version: 14
java-version: 16
- name: Set env
run: echo "RELEASE_VERSION=${GITHUB_REF#refs/*/}" >> $GITHUB_ENV
- name: Add Arc release

View File

@ -3,15 +3,15 @@ name: Pull Request Tests
on: [pull_request, workflow_dispatch]
jobs:
buildJava14:
testPR:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up JDK 14
- name: Set up JDK 16
uses: actions/setup-java@v1
with:
java-version: 14
java-version: 16
- name: Run unit tests and build JAR
run: ./gradlew test desktop:dist
- name: Upload desktop JAR for testing

View File

@ -3,7 +3,7 @@ name: Tests
on: [push, workflow_dispatch]
jobs:
buildJava14:
runPush:
runs-on: ubuntu-latest
steps:
@ -17,9 +17,9 @@ jobs:
git tag ${BNUM}
git config --global user.name "Build Uploader"
git push https://Anuken:${{ secrets.API_TOKEN_GITHUB }}@github.com/Anuken/MindustryBuilds ${BNUM}
- name: Set up JDK 14
- name: Set up JDK 16
uses: actions/setup-java@v1
with:
java-version: 14
java-version: 16
- name: Run unit tests
run: ./gradlew clean cleanTest test

View File

@ -18,7 +18,7 @@ See [CONTRIBUTING](CONTRIBUTING.md).
Bleeding-edge builds are generated automatically for every commit. You can see them [here](https://github.com/Anuken/MindustryBuilds/releases).
If you'd rather compile on your own, follow these instructions.
First, make sure you have [JDK 14](https://adoptopenjdk.net/archive.html?variant=openjdk14&jvmVariant=hotspot) installed. **Other JDK versions will not work.** Open a terminal in the Mindustry directory and run the following commands:
First, make sure you have [JDK 16](https://adoptopenjdk.net/archive.html?variant=openjdk16&jvmVariant=hotspot) installed. **Other JDK versions will not work.** Open a terminal in the Mindustry directory and run the following commands:
### Windows

View File

@ -7,9 +7,7 @@ buildscript{
}
dependencies{
//IMPORTANT NOTICE: any version of the plugin after 3.4.1 will break builds
//it appears abstract methods don't get desugared properly (if at all)
classpath 'com.android.tools.build:gradle:3.4.1'
classpath 'com.android.tools.build:gradle:7.1.0-alpha02'
}
}

View File

@ -62,13 +62,6 @@ public class AndroidRhinoContext{
initApplicationClassLoader(createClassLoader(AndroidContextFactory.class.getClassLoader()));
}
@Override
protected Context makeContext(){
Context ctx = super.makeContext();
ctx.setClassShutter(Scripts::allowClass);
return ctx;
}
/**
* Create a ClassLoader which is able to deal with bytecode
* @param parent the parent of the create classloader

View File

@ -196,12 +196,7 @@ allprojects{
tasks.withType(JavaCompile){
targetCompatibility = 8
//TODO fix dynamically, this is a hack
if(System.getProperty("user.name") == "anuke"){
sourceCompatibility = JavaVersion.VERSION_15
}else{
sourceCompatibility = JavaVersion.VERSION_14
}
sourceCompatibility = JavaVersion.VERSION_16
options.encoding = "UTF-8"
options.compilerArgs += ["-Xlint:deprecation"]
dependsOn clearCache
@ -224,18 +219,13 @@ configure(project(":annotations")){
//compile with java 8 compatibility for everything except the annotation project
configure(subprojects - project(":annotations")){
tasks.withType(JavaCompile){
options.compilerArgs.addAll(['--release', '8', '--enable-preview'])
doFirst{
options.compilerArgs = options.compilerArgs.findAll{it != '--enable-preview' }
}
options.compilerArgs.addAll(['--release', '8'])
}
tasks.withType(Javadoc){
options{
addStringOption('Xdoclint:none', '-quiet')
addBooleanOption('-enable-preview', true)
addStringOption('-release', '14')
addStringOption('-release', '16')
}
}
}
@ -302,9 +292,8 @@ project(":core"){
kapt{
javacOptions{
option("-source", "14")
option("-source", "16")
option("-target", "1.8")
option("--enable-preview")
}
}
@ -430,6 +419,8 @@ project(":tests"){
}
test{
//fork every test so mods don't interact with each other
forkEvery = 1
useJUnitPlatform()
workingDir = new File("../core/assets")
testLogging{

View File

@ -83,7 +83,7 @@ public abstract class ClientLauncher extends ApplicationCore implements Platform
Fonts.loadDefaultFont();
//load fallback atlas if max texture size is below 4096
assets.load(new AssetDescriptor<>(maxTextureSize >= 4096 ? "sprites/sprites.aatls" : "sprites/fallback/sprites.aatls", TextureAtlas.class)).loaded = t -> atlas = (TextureAtlas)t;
assets.load(new AssetDescriptor<>(maxTextureSize >= 4096 ? "sprites/sprites.aatls" : "sprites/fallback/sprites.aatls", TextureAtlas.class)).loaded = t -> atlas = (TextureAtlas)t;
assets.loadRun("maps", Map.class, () -> maps.loadPreviews());
Musics.load();

View File

@ -289,7 +289,7 @@ public class BaseAI{
}
Tile o = world.tile(tile.x + p.x, tile.y + p.y);
if(o != null && (o.block() instanceof PayloadBlock || o.block() instanceof PayloadConveyor)){
if(o != null && (o.block() instanceof PayloadBlock || o.block() instanceof PayloadConveyor || o.block() instanceof ShockMine)){
continue outer;
}

View File

@ -16,7 +16,6 @@ import mindustry.world.blocks.defense.*;
import mindustry.world.blocks.defense.turrets.*;
import mindustry.world.blocks.distribution.*;
import mindustry.world.blocks.environment.*;
import mindustry.world.blocks.experimental.*;
import mindustry.world.blocks.legacy.*;
import mindustry.world.blocks.liquid.*;
import mindustry.world.blocks.logic.*;

View File

@ -612,9 +612,9 @@ public class UnitTypes implements ContentList{
bullet = new LiquidBulletType(Liquids.slag){{
damage = 11;
speed = 2.4f;
drag = 0.01f;
drag = 0.009f;
shootEffect = Fx.shootSmall;
lifetime = 56f;
lifetime = 57f;
collidesAir = false;
}};
}});

View File

@ -323,13 +323,14 @@ public class Control implements ApplicationListener, Loadable{
if(slot != null && !clearSectors){
try{
boolean hadNoCore = !sector.info.hasCore;
reloader.begin();
slot.load();
slot.setAutosave(true);
state.rules.sector = sector;
//if there is no base, simulate a new game and place the right loadout at the spawn position
if(state.rules.defaultTeam.cores().isEmpty()){
if(state.rules.defaultTeam.cores().isEmpty() || hadNoCore){
//no spawn set -> delete the sector save
if(sector.info.spawnPosition == 0){

View File

@ -79,15 +79,6 @@ public interface Platform{
}
default Context getScriptContext(){
ContextFactory.getGlobalSetter().setContextFactoryGlobal(new ContextFactory(){
@Override
protected Context makeContext(){
Context ctx = super.makeContext();
ctx.setClassShutter(Scripts::allowClass);
return ctx;
}
});
Context c = Context.enter();
c.setOptimizationLevel(9);
return c;

View File

@ -164,7 +164,7 @@ public class MapGenerateDialog extends BaseDialog{
for(int x = 0; x < editor.width(); x++){
for(int y = 0; y < editor.height(); y++){
Tile tile = editor.tile(x, y);
input.apply(x, y, tile.block(), tile.floor(), tile.overlay());
input.set(x, y, tile.block(), tile.floor(), tile.overlay());
filter.apply(input);
writeTiles[x + y*world.width()] = PackTile.get(input.block.id, input.floor.id, input.overlay.id);
}
@ -340,6 +340,7 @@ public class MapGenerateDialog extends BaseDialog{
if(filter.isPost() && applied) continue;
p.button((icon == '\0' ? "" : icon + " ") + filter.name(), Styles.cleart, () -> {
filter.randomize();
filters.add(filter);
rebuildFilters();
update();
@ -419,7 +420,7 @@ public class MapGenerateDialog extends BaseDialog{
pixmap.each((px, py) -> {
int x = px * scaling, y = py * scaling;
long tile = buffer1[px + py * w];
input.apply(x, y, content.block(PackTile.block(tile)), content.block(PackTile.floor(tile)), content.block(PackTile.overlay(tile)));
input.set(x, y, content.block(PackTile.block(tile)), content.block(PackTile.floor(tile)), content.block(PackTile.overlay(tile)));
filter.apply(input);
buffer2[px + py * w] = PackTile.get(input.block.id, input.floor.id, input.overlay.id);
});

View File

@ -3,6 +3,7 @@ package mindustry.editor;
import arc.*;
import arc.scene.ui.*;
import arc.struct.*;
import arc.util.*;
import mindustry.*;
import mindustry.game.*;
import mindustry.io.*;
@ -73,8 +74,12 @@ public class MapInfoDialog extends BaseDialog{
t.row();
t.add("@editor.generation").padRight(8).left();
t.button("@edit", () -> {
generate.show(Vars.maps.readFilters(editor.tags.get("genfilters", "")),
filters -> editor.tags.put("genfilters", JsonIO.write(filters)));
generate.show(maps.readFilters(editor.tags.get("genfilters", "")),
filters -> {
//reset seed to 0 so it is not written
filters.each(f -> f.seed = 0);
editor.tags.put("genfilters", JsonIO.write(filters));
});
hide();
}).left().width(200f);

View File

@ -59,12 +59,12 @@ public class ParticleEffect extends Effect{
Angles.randLenVectors(e.id, particles, length * fin + baseLength, e.rotation, cone, (x, y) -> {
Lines.lineAngle(ox + x, oy + y, Mathf.angle(x, y), len);
Drawf.light(ox + x, oy + y, len * lightScl, lightColor, lightOpacity);
Drawf.light(ox + x, oy + y, len * lightScl, lightColor, lightOpacity* Draw.getColor().a);
});
}else{
Angles.randLenVectors(e.id, particles, length * fin + baseLength, e.rotation, cone, (x, y) -> {
Draw.rect(tex, ox + x, oy + y, rad, rad, e.rotation + offset + e.time * spin);
Drawf.light(ox + x, oy + y, rad * lightScl, lightColor, lightOpacity);
Drawf.light(ox + x, oy + y, rad * lightScl, lightColor, lightOpacity * Draw.getColor().a);
});
}
}

View File

@ -3,6 +3,7 @@ package mindustry.graphics;
import arc.*;
import arc.graphics.*;
import arc.graphics.gl.*;
import arc.util.*;
import static mindustry.Vars.*;
@ -53,7 +54,7 @@ public class CacheLayer{
}
public static class ShaderLayer extends CacheLayer{
public Shader shader;
public @Nullable Shader shader;
public ShaderLayer(Shader shader){
//shader will be null on headless backend, but that's ok

View File

@ -44,9 +44,7 @@ public class MenuRenderer implements Disposable{
Seq<Block> ores = content.blocks().select(b -> b instanceof OreBlock && !(b instanceof WallOreBlock));
shadows = new FrameBuffer(width, height);
int offset = Mathf.random(100000);
Simplex s1 = new Simplex(offset);
Simplex s2 = new Simplex(offset + 1);
Simplex s3 = new Simplex(offset + 2);
int s1 = offset, s2 = offset + 1, s3 = offset + 2;
Block[] selected = Structs.select(
new Block[]{Blocks.sand, Blocks.sandWall},
new Block[]{Blocks.shale, Blocks.shaleWall},
@ -85,27 +83,27 @@ public class MenuRenderer implements Disposable{
Block ore = Blocks.air;
Block wall = Blocks.air;
if(s1.octaveNoise2D(3, 0.5, 1/20.0, x, y) > 0.5){
if(Simplex.noise2d(s1, 3, 0.5, 1/20.0, x, y) > 0.5){
wall = walld;
}
if(s3.octaveNoise2D(3, 0.5, 1/20.0, x, y) > 0.5){
if(Simplex.noise2d(s3, 3, 0.5, 1/20.0, x, y) > 0.5){
floor = floord2;
if(wall != Blocks.air){
wall = walld2;
}
}
if(s2.octaveNoise2D(3, 0.3, 1/30.0, x, y) > tr1){
if(Simplex.noise2d(s2, 3, 0.3, 1/30.0, x, y) > tr1){
ore = ore1;
}
if(s2.octaveNoise2D(2, 0.2, 1/15.0, x, y+99999) > tr2){
if(Simplex.noise2d(s2, 2, 0.2, 1/15.0, x, y+99999) > tr2){
ore = ore2;
}
if(doheat){
double heat = s3.octaveNoise2D(4, 0.6, 1 / 50.0, x, y + 9999);
double heat = Simplex.noise2d(s3, 4, 0.6, 1 / 50.0, x, y + 9999);
double base = 0.65;
if(heat > base){
@ -126,7 +124,7 @@ public class MenuRenderer implements Disposable{
if(tech){
int mx = x % secSize, my = y % secSize;
int sclx = x / secSize, scly = y / secSize;
if(s1.octaveNoise2D(2, 1f / 10f, 0.5f, sclx, scly) > 0.4f && (mx == 0 || my == 0 || mx == secSize - 1 || my == secSize - 1)){
if(Simplex.noise2d(s1, 2, 1f / 10f, 0.5f, sclx, scly) > 0.4f && (mx == 0 || my == 0 || mx == secSize - 1 || my == secSize - 1)){
floor = Blocks.darkPanel3;
if(Mathf.dst(mx, my, secSize/2, secSize/2) > secSize/2f + 1){
floor = Blocks.darkPanel4;
@ -140,7 +138,7 @@ public class MenuRenderer implements Disposable{
}
if(tendrils){
if(RidgedPerlin.noise2d(1 + offset, x, y, 1f / 17f) > 0f){
if(Ridged.noise2d(1 + offset, x, y, 1f / 17f) > 0f){
floor = Mathf.chance(0.2) ? Blocks.sporeMoss : Blocks.moss;
if(wall != Blocks.air){

View File

@ -12,7 +12,6 @@ public class SunMesh extends HexMesh{
public SunMesh(Planet planet, int divisions, double octaves, double persistence, double scl, double pow, double mag, float colorScale, Color... colors){
super(planet, new HexMesher(){
Simplex sim = new Simplex();
@Override
public float getHeight(Vec3 position){
@ -21,7 +20,7 @@ public class SunMesh extends HexMesh{
@Override
public Color getColor(Vec3 position){
double height = Math.pow(sim.octaveNoise3D(octaves, persistence, scl, position.x, position.y, position.z), pow) * mag;
double height = Math.pow(Simplex.noise3d(0, octaves, persistence, scl, position.x, position.y, position.z), pow) * mag;
return Tmp.c1.set(colors[Mathf.clamp((int)(height * colors.length), 0, colors.length - 1)]).mul(colorScale);
}
}, divisions, Shaders.unlit);

View File

@ -28,9 +28,6 @@ import static mindustry.Vars.*;
public class LExecutor{
public static final int maxInstructions = 1000;
//for noise operations
public static final Simplex noise = new Simplex();
//special variables
public static final int
varCounter = 0,

View File

@ -2,6 +2,7 @@ package mindustry.logic;
import arc.math.*;
import arc.util.*;
import arc.util.noise.*;
public enum LogicOp{
add("+", (a, b) -> a + b),
@ -32,7 +33,7 @@ public enum LogicOp{
min("min", true, Math::min),
angle("angle", true, (x, y) -> Angles.angle((float)x, (float)y)),
len("len", true, (x, y) -> Mathf.dst((float)x, (float)y)),
noise("noise", true, LExecutor.noise::rawNoise2D),
noise("noise", true, (x, y) -> Simplex.raw2d(0, x, y)),
abs("abs", a -> Math.abs(a)),
log("log", Math::log),
log10("log10", Math::log10),

View File

@ -1,6 +1,5 @@
package mindustry.maps.filters;
import arc.util.*;
import mindustry.content.*;
import mindustry.gen.*;
import mindustry.world.*;
@ -13,12 +12,12 @@ public class BlendFilter extends GenerateFilter{
@Override
public FilterOption[] options(){
return Structs.arr(
new SliderOption("radius", () -> radius, f -> radius = f, 1f, 10f),
new BlockOption("block", () -> block, b -> block = b, anyOptional),
new BlockOption("floor", () -> floor, b -> floor = b, anyOptional),
new BlockOption("ignore", () -> ignore, b -> ignore = b, floorsOptional)
);
return new FilterOption[]{
new SliderOption("radius", () -> radius, f -> radius = f, 1f, 10f),
new BlockOption("block", () -> block, b -> block = b, anyOptional),
new BlockOption("floor", () -> floor, b -> floor = b, anyOptional),
new BlockOption("ignore", () -> ignore, b -> ignore = b, floorsOptional)
};
}
@Override
@ -32,7 +31,7 @@ public class BlendFilter extends GenerateFilter{
}
@Override
public void apply(){
public void apply(GenerateInput in){
if(in.floor == block || block == Blocks.air || in.floor == ignore || (!floor.isFloor() && (in.block == block || in.block == ignore))) return;
int rad = (int)radius;

View File

@ -1,6 +1,5 @@
package mindustry.maps.filters;
import arc.util.*;
import mindustry.content.*;
import mindustry.gen.*;
import mindustry.world.*;
@ -12,7 +11,9 @@ public class ClearFilter extends GenerateFilter{
@Override
public FilterOption[] options(){
return Structs.arr(new BlockOption("block", () -> block, b -> block = b, b -> oresOnly.get(b) || wallsOnly.get(b)));
return new BlockOption[]{
new BlockOption("block", () -> block, b -> block = b, b -> oresOnly.get(b) || wallsOnly.get(b))
};
}
@Override
@ -21,7 +22,7 @@ public class ClearFilter extends GenerateFilter{
}
@Override
public void apply(){
public void apply(GenerateInput in){
if(in.block == block){
in.block = Blocks.air;

View File

@ -1,7 +1,6 @@
package mindustry.maps.filters;
import arc.struct.*;
import arc.util.*;
import mindustry.gen.*;
import mindustry.world.*;
import mindustry.world.blocks.storage.*;
@ -14,10 +13,9 @@ public class CoreSpawnFilter extends GenerateFilter{
@Override
public FilterOption[] options(){
return Structs.arr(
//disabled until necessary
// SliderOption("amount", () -> amount, f -> amount = (int)f, 1, 10).display()
);
return new FilterOption[]{};
}
@Override

View File

@ -1,6 +1,5 @@
package mindustry.maps.filters;
import arc.util.*;
import mindustry.gen.*;
import mindustry.maps.filters.FilterOption.*;
import mindustry.world.*;
@ -10,10 +9,10 @@ public class DistortFilter extends GenerateFilter{
@Override
public FilterOption[] options(){
return Structs.arr(
new SliderOption("scale", () -> scl, f -> scl = f, 1f, 200f),
new SliderOption("mag", () -> mag, f -> mag = f, 0.5f, 100f)
);
return new SliderOption[]{
new SliderOption("scale", () -> scl, f -> scl = f, 1f, 200f),
new SliderOption("mag", () -> mag, f -> mag = f, 0.5f, 100f)
};
}
@Override
@ -27,8 +26,8 @@ public class DistortFilter extends GenerateFilter{
}
@Override
public void apply(){
Tile tile = in.tile(in.x + noise(in.x, in.y, scl, mag) - mag / 2f, in.y + noise(in.x, in.y + o, scl, mag) - mag / 2f);
public void apply(GenerateInput in){
Tile tile = in.tile(in.x + noise(in, scl, mag) - mag / 2f, in.y + noise(in, scl, mag) - mag / 2f);
in.floor = tile.floor();
if(!tile.block().synthetic() && !in.block.synthetic()) in.block = tile.block();

View File

@ -1,7 +1,6 @@
package mindustry.maps.filters;
import arc.struct.*;
import arc.util.*;
import mindustry.content.*;
import mindustry.gen.*;
import mindustry.maps.filters.FilterOption.*;
@ -13,9 +12,9 @@ public class EnemySpawnFilter extends GenerateFilter{
@Override
public FilterOption[] options(){
return Structs.arr(
new SliderOption("amount", () -> amount, f -> amount = (int)f, 1, 10).display()
);
return new SliderOption[]{
new SliderOption("amount", () -> amount, f -> amount = (int)f, 1, 10).display()
};
}
@Override

View File

@ -12,12 +12,9 @@ import mindustry.gen.*;
import mindustry.world.*;
public abstract class GenerateFilter{
protected transient float o = (float)(Math.random() * 10000000.0);
protected transient int seed;
protected transient GenerateInput in;
public int seed = 0;
public void apply(Tiles tiles, GenerateInput in){
this.in = in;
if(isBuffered()){
//buffer of tiles used, each tile packed into a long struct
@ -26,8 +23,8 @@ public abstract class GenerateFilter{
for(int i = 0; i < tiles.width * tiles.height; i++){
Tile tile = tiles.geti(i);
in.apply(tile.x, tile.y, tile.block(), tile.floor(), tile.overlay());
apply();
in.set(tile.x, tile.y, tile.block(), tile.floor(), tile.overlay());
apply(in);
buffer[i] = PackTile.get(in.block.id, in.floor.id, in.overlay.id);
}
@ -48,8 +45,8 @@ public abstract class GenerateFilter{
}
}else{
for(Tile tile : tiles){
in.apply(tile.x, tile.y, tile.block(), tile.floor(), tile.overlay());
apply();
in.set(tile.x, tile.y, tile.block(), tile.floor(), tile.overlay());
apply(in);
tile.setFloor(in.floor.asFloor());
tile.setOverlay(!in.floor.asFloor().hasSurface() && in.overlay.asFloor().needsSurface ? Blocks.air : in.overlay);
@ -61,16 +58,11 @@ public abstract class GenerateFilter{
}
}
public final void apply(GenerateInput in){
this.in = in;
apply();
}
/** @return a new array of options for configuring this filter */
public abstract FilterOption[] options();
/** apply the actual filter on the input */
protected void apply(){}
public void apply(GenerateInput in){}
/** draw any additional guides */
public void draw(Image image){}
@ -93,7 +85,7 @@ public abstract class GenerateFilter{
/** set the seed to a random number */
public void randomize(){
seed = Mathf.random(99999999);
seed = Mathf.random(999999999);
}
/** @return whether this filter needs a read/write buffer (e.g. not a 1:1 tile mapping). */
@ -108,24 +100,26 @@ public abstract class GenerateFilter{
//utility generation functions
protected float noise(float x, float y, float scl, float mag){
return (float)in.noise.octaveNoise2D(1f, 0f, 1f / scl, x + o, y + o) * mag;
//TODO would be nice if these functions used the seed and ditched "in" completely; simplex should be stateless
protected float noise(GenerateInput in, float scl, float mag){
return (float)Simplex.noise2d(seed, 1f, 0f, 1f / scl, in.x, in.y) * mag;
}
protected float noise(float x, float y, float scl, float mag, float octaves, float persistence){
return (float)in.noise.octaveNoise2D(octaves, persistence, 1f / scl, x + o, y + o) * mag;
protected float noise(GenerateInput in, float scl, float mag, float octaves, float persistence){
return (float)Simplex.noise2d(seed, octaves, persistence, 1f / scl, in.x, in.y) * mag;
}
protected float rnoise(float x, float y, float scl, float mag){
return RidgedPerlin.noise2d(seed + 1, (int)(x + o), (int)(y + o), 1f / scl) * mag;
return Ridged.noise2d(seed + 1, (int)(x), (int)(y), 1f / scl) * mag;
}
protected float rnoise(float x, float y, int octaves, float scl, float falloff, float mag){
return RidgedPerlin.noise2d(seed + 1, (int)(x + o), (int)(y + o), octaves, falloff, 1f / scl) * mag;
return Ridged.noise2d(seed + 1, (int)(x), (int)(y), octaves, falloff, 1f / scl) * mag;
}
protected float chance(){
return Mathf.randomSeed(Pack.longInt(in.x, in.y + seed));
protected float chance(int x, int y){
return Mathf.randomSeed(Pack.longInt(x, y + seed));
}
/** an input for generating at a certain coordinate. should only be instantiated once. */
@ -137,10 +131,9 @@ public abstract class GenerateFilter{
/** output parameters */
public Block floor, block, overlay;
Simplex noise = new Simplex();
TileProvider buffer;
public void apply(int x, int y, Block block, Block floor, Block overlay){
public void set(int x, int y, Block block, Block floor, Block overlay){
this.floor = floor;
this.block = block;
this.overlay = overlay;
@ -152,7 +145,6 @@ public abstract class GenerateFilter{
this.buffer = buffer;
this.width = width;
this.height = height;
noise.setSeed(filter.seed);
}
Tile tile(float x, float y){

View File

@ -2,7 +2,6 @@ package mindustry.maps.filters;
import arc.math.*;
import arc.struct.*;
import arc.util.*;
import mindustry.gen.*;
import mindustry.maps.filters.FilterOption.*;
import mindustry.world.*;
@ -17,10 +16,10 @@ public class MedianFilter extends GenerateFilter{
@Override
public FilterOption[] options(){
return Structs.arr(
new SliderOption("radius", () -> radius, f -> radius = f, 1f, 10f),
new SliderOption("percentile", () -> percentile, f -> percentile = f, 0f, 1f)
);
return new SliderOption[]{
new SliderOption("radius", () -> radius, f -> radius = f, 1f, 10f),
new SliderOption("percentile", () -> percentile, f -> percentile = f, 0f, 1f)
};
}
@Override
@ -34,7 +33,7 @@ public class MedianFilter extends GenerateFilter{
}
@Override
public void apply(){
public void apply(GenerateInput in){
int rad = (int)radius;
blocks.clear();
floors.clear();

View File

@ -12,17 +12,17 @@ import mindustry.maps.filters.FilterOption.*;
import mindustry.world.*;
public class MirrorFilter extends GenerateFilter{
private final Vec2 v1 = new Vec2(), v2 = new Vec2(), v3 = new Vec2();
private static final Vec2 v1 = new Vec2(), v2 = new Vec2(), v3 = new Vec2();
int angle = 45;
boolean rotate = false;
@Override
public FilterOption[] options(){
return Structs.arr(
new SliderOption("angle", () -> angle, f -> angle = (int)f, 0, 360, 45),
new ToggleOption("rotate", () -> rotate, f -> rotate = f)
);
return new FilterOption[]{
new SliderOption("angle", () -> angle, f -> angle = (int)f, 0, 360, 45),
new ToggleOption("rotate", () -> rotate, f -> rotate = f)
};
}
@Override
@ -31,7 +31,7 @@ public class MirrorFilter extends GenerateFilter{
}
@Override
protected void apply(){
public void apply(GenerateInput in){
v1.trnsExact(angle - 90, 1f);
v2.set(v1).scl(-1f);
@ -41,7 +41,7 @@ public class MirrorFilter extends GenerateFilter{
v3.set(in.x, in.y);
if(!left(v1, v2, v3)){
mirror(v3, v1.x, v1.y, v2.x, v2.y);
mirror(in.width, in.height, v3, v1.x, v1.y, v2.x, v2.y);
Tile tile = in.tile(v3.x, v3.y);
in.floor = tile.floor();
if(!tile.block().synthetic()){
@ -73,11 +73,11 @@ public class MirrorFilter extends GenerateFilter{
Draw.reset();
}
void mirror(Vec2 p, float x0, float y0, float x1, float y1){
void mirror(int width, int height, Vec2 p, float x0, float y0, float x1, float y1){
//special case: uneven map mirrored at 45 degree angle (or someone might just want rotational symmetry)
if((in.width != in.height && angle % 90 != 0) || rotate){
p.x = in.width - p.x - 1;
p.y = in.height - p.y - 1;
if((width != height && angle % 90 != 0) || rotate){
p.x = width - p.x - 1;
p.y = height - p.y - 1;
}else{
float dx = x1 - x0;
float dy = y1 - y0;

View File

@ -1,6 +1,5 @@
package mindustry.maps.filters;
import arc.util.*;
import mindustry.content.*;
import mindustry.gen.*;
import mindustry.world.*;
@ -13,15 +12,15 @@ public class NoiseFilter extends GenerateFilter{
@Override
public FilterOption[] options(){
return Structs.arr(
new SliderOption("scale", () -> scl, f -> scl = f, 1f, 500f),
new SliderOption("threshold", () -> threshold, f -> threshold = f, 0f, 1f),
new SliderOption("octaves", () -> octaves, f -> octaves = f, 1f, 10f),
new SliderOption("falloff", () -> falloff, f -> falloff = f, 0f, 1f),
new BlockOption("target", () -> target, b -> target = b, anyOptional),
new BlockOption("floor", () -> floor, b -> floor = b, floorsOptional),
new BlockOption("wall", () -> block, b -> block = b, wallsOptional)
);
return new FilterOption[]{
new SliderOption("scale", () -> scl, f -> scl = f, 1f, 500f),
new SliderOption("threshold", () -> threshold, f -> threshold = f, 0f, 1f),
new SliderOption("octaves", () -> octaves, f -> octaves = f, 1f, 10f),
new SliderOption("falloff", () -> falloff, f -> falloff = f, 0f, 1f),
new BlockOption("target", () -> target, b -> target = b, anyOptional),
new BlockOption("floor", () -> floor, b -> floor = b, floorsOptional),
new BlockOption("wall", () -> block, b -> block = b, wallsOptional)
};
}
@Override
@ -30,8 +29,8 @@ public class NoiseFilter extends GenerateFilter{
}
@Override
public void apply(){
float noise = noise(in.x, in.y, scl, 1f, octaves, falloff);
public void apply(GenerateInput in){
float noise = noise(in, scl, 1f, octaves, falloff);
if(noise > threshold && (target == Blocks.air || in.floor == target || in.block == target)){
if(floor != Blocks.air) in.floor = floor;

View File

@ -1,6 +1,5 @@
package mindustry.maps.filters;
import arc.util.*;
import mindustry.content.*;
import mindustry.gen.*;
import mindustry.world.*;
@ -13,14 +12,14 @@ public class OreFilter extends GenerateFilter{
@Override
public FilterOption[] options(){
return Structs.arr(
new SliderOption("scale", () -> scl, f -> scl = f, 1f, 500f),
new SliderOption("threshold", () -> threshold, f -> threshold = f, 0f, 1f),
new SliderOption("octaves", () -> octaves, f -> octaves = f, 1f, 10f),
new SliderOption("falloff", () -> falloff, f -> falloff = f, 0f, 1f),
new BlockOption("ore", () -> ore, b -> ore = b, oresOnly),
new BlockOption("target", () -> target, b -> target = b, oresFloorsOptional)
);
return new FilterOption[]{
new SliderOption("scale", () -> scl, f -> scl = f, 1f, 500f),
new SliderOption("threshold", () -> threshold, f -> threshold = f, 0f, 1f),
new SliderOption("octaves", () -> octaves, f -> octaves = f, 1f, 10f),
new SliderOption("falloff", () -> falloff, f -> falloff = f, 0f, 1f),
new BlockOption("ore", () -> ore, b -> ore = b, oresOnly),
new BlockOption("target", () -> target, b -> target = b, oresFloorsOptional)
};
}
@Override
@ -29,8 +28,8 @@ public class OreFilter extends GenerateFilter{
}
@Override
public void apply(){
float noise = noise(in.x, in.y, scl, 1f, octaves, falloff);
public void apply(GenerateInput in){
float noise = noise(in, scl, 1f, octaves, falloff);
if(noise > threshold && in.overlay != Blocks.spawn && (target == Blocks.air || in.floor == target || in.overlay == target) && in.floor.asFloor().hasSurface()){
in.overlay = ore;

View File

@ -2,7 +2,6 @@ package mindustry.maps.filters;
import arc.math.*;
import arc.struct.*;
import arc.util.*;
import mindustry.*;
import mindustry.content.*;
import mindustry.gen.*;
@ -17,10 +16,10 @@ public class OreMedianFilter extends GenerateFilter{
@Override
public FilterOption[] options(){
return Structs.arr(
new SliderOption("radius", () -> radius, f -> radius = f, 1f, 12f),
new SliderOption("percentile", () -> percentile, f -> percentile = f, 0f, 1f)
);
return new SliderOption[]{
new SliderOption("radius", () -> radius, f -> radius = f, 1f, 12f),
new SliderOption("percentile", () -> percentile, f -> percentile = f, 0f, 1f)
};
}
@Override
@ -34,7 +33,7 @@ public class OreMedianFilter extends GenerateFilter{
}
@Override
public void apply(){
public void apply(GenerateInput in){
if(in.overlay == Blocks.spawn) return;
int cx = (in.x / 2) * 2;

View File

@ -1,6 +1,5 @@
package mindustry.maps.filters;
import arc.util.*;
import mindustry.content.*;
import mindustry.gen.*;
import mindustry.world.*;
@ -13,16 +12,16 @@ public class RiverNoiseFilter extends GenerateFilter{
@Override
public FilterOption[] options(){
return Structs.arr(
new SliderOption("scale", () -> scl, f -> scl = f, 1f, 500f),
new SliderOption("threshold", () -> threshold, f -> threshold = f, -1f, 1f),
new SliderOption("threshold2", () -> threshold2, f -> threshold2 = f, -1f, 1f),
new SliderOption("octaves", () -> octaves, f -> octaves = f, 1f, 10f),
new SliderOption("falloff", () -> falloff, f -> falloff = f, 0f, 1f),
new BlockOption("block", () -> block, b -> block = b, wallsOnly),
new BlockOption("floor", () -> floor, b -> floor = b, floorsOnly),
new BlockOption("floor2", () -> floor2, b -> floor2 = b, floorsOnly)
);
return new FilterOption[]{
new SliderOption("scale", () -> scl, f -> scl = f, 1f, 500f),
new SliderOption("threshold", () -> threshold, f -> threshold = f, -1f, 1f),
new SliderOption("threshold2", () -> threshold2, f -> threshold2 = f, -1f, 1f),
new SliderOption("octaves", () -> octaves, f -> octaves = f, 1f, 10f),
new SliderOption("falloff", () -> falloff, f -> falloff = f, 0f, 1f),
new BlockOption("block", () -> block, b -> block = b, wallsOnly),
new BlockOption("floor", () -> floor, b -> floor = b, floorsOnly),
new BlockOption("floor2", () -> floor2, b -> floor2 = b, floorsOnly)
};
}
@Override
@ -31,7 +30,7 @@ public class RiverNoiseFilter extends GenerateFilter{
}
@Override
public void apply(){
public void apply(GenerateInput in){
float noise = rnoise(in.x, in.y, (int)octaves, scl, falloff, 1f);
if(noise >= threshold){

View File

@ -1,6 +1,5 @@
package mindustry.maps.filters;
import arc.util.*;
import mindustry.content.*;
import mindustry.gen.*;
import mindustry.world.*;
@ -13,12 +12,12 @@ public class ScatterFilter extends GenerateFilter{
@Override
public FilterOption[] options(){
return Structs.arr(
new SliderOption("chance", () -> chance, f -> chance = f, 0f, 1f),
new BlockOption("flooronto", () -> flooronto, b -> flooronto = b, floorsOptional),
new BlockOption("floor", () -> floor, b -> floor = b, floorsOptional),
new BlockOption("block", () -> block, b -> block = b, wallsOresOptional)
);
return new FilterOption[]{
new SliderOption("chance", () -> chance, f -> chance = f, 0f, 1f),
new BlockOption("flooronto", () -> flooronto, b -> flooronto = b, floorsOptional),
new BlockOption("floor", () -> floor, b -> floor = b, floorsOptional),
new BlockOption("block", () -> block, b -> block = b, wallsOresOptional)
};
}
@Override
@ -27,9 +26,9 @@ public class ScatterFilter extends GenerateFilter{
}
@Override
public void apply(){
public void apply(GenerateInput in){
if(block != Blocks.air && (in.floor == flooronto || flooronto == Blocks.air) && in.block == Blocks.air && chance() <= chance){
if(block != Blocks.air && (in.floor == flooronto || flooronto == Blocks.air) && in.block == Blocks.air && chance(in.x, in.y) <= chance){
if(!block.isOverlay()){
in.block = block;
}else{
@ -37,7 +36,7 @@ public class ScatterFilter extends GenerateFilter{
}
}
if(floor != Blocks.air && (in.floor == flooronto || flooronto == Blocks.air) && chance() <= chance){
if(floor != Blocks.air && (in.floor == flooronto || flooronto == Blocks.air) && chance(in.x, in.y) <= chance){
in.floor = floor;
}
}

View File

@ -19,9 +19,9 @@ public class SpawnPathFilter extends GenerateFilter{
@Override
public FilterOption[] options(){
return Structs.arr(
new SliderOption("radius", () -> radius, f -> radius = (int)f, 1, 20).display()
);
return new SliderOption[]{
new SliderOption("radius", () -> radius, f -> radius = (int)f, 1, 20).display()
};
}
@Override

View File

@ -1,7 +1,6 @@
package mindustry.maps.filters;
import arc.math.*;
import arc.util.*;
import mindustry.content.*;
import mindustry.gen.*;
import mindustry.world.*;
@ -14,16 +13,16 @@ public class TerrainFilter extends GenerateFilter{
@Override
public FilterOption[] options(){
return Structs.arr(
new SliderOption("scale", () -> scl, f -> scl = f, 1f, 500f),
new SliderOption("mag", () -> magnitude, f -> magnitude = f, 0f, 2f),
new SliderOption("threshold", () -> threshold, f -> threshold = f, 0f, 1f),
new SliderOption("circle-scale", () -> circleScl, f -> circleScl = f, 0f, 3f),
new SliderOption("octaves", () -> octaves, f -> octaves = f, 1f, 10f),
new SliderOption("falloff", () -> falloff, f -> falloff = f, 0f, 1f),
new BlockOption("floor", () -> floor, b -> floor = b, floorsOptional),
new BlockOption("wall", () -> block, b -> block = b, wallsOnly)
);
return new FilterOption[]{
new SliderOption("scale", () -> scl, f -> scl = f, 1f, 500f),
new SliderOption("mag", () -> magnitude, f -> magnitude = f, 0f, 2f),
new SliderOption("threshold", () -> threshold, f -> threshold = f, 0f, 1f),
new SliderOption("circle-scale", () -> circleScl, f -> circleScl = f, 0f, 3f),
new SliderOption("octaves", () -> octaves, f -> octaves = f, 1f, 10f),
new SliderOption("falloff", () -> falloff, f -> falloff = f, 0f, 1f),
new BlockOption("floor", () -> floor, b -> floor = b, floorsOptional),
new BlockOption("wall", () -> block, b -> block = b, wallsOnly)
};
}
@Override
@ -32,8 +31,8 @@ public class TerrainFilter extends GenerateFilter{
}
@Override
public void apply(){
float noise = noise(in.x, in.y, scl, magnitude, octaves, falloff) + Mathf.dst((float)in.x / in.width, (float)in.y / in.height, 0.5f, 0.5f) * circleScl;
public void apply(GenerateInput in){
float noise = noise(in, scl, magnitude, octaves, falloff) + Mathf.dst((float)in.x / in.width, (float)in.y / in.height, 0.5f, 0.5f) * circleScl;
if(floor != Blocks.air){
in.floor = floor;

View File

@ -18,7 +18,6 @@ import static mindustry.Vars.*;
public abstract class PlanetGenerator extends BasicGenerator implements HexMesher{
protected IntSeq ints = new IntSeq();
protected Sector sector;
protected Simplex noise = new Simplex();
/** Should generate sector bases for a planet. */
public void generateSector(Sector sector){
@ -116,7 +115,7 @@ public abstract class PlanetGenerator extends BasicGenerator implements HexMeshe
@Override
protected float noise(float x, float y, double octaves, double falloff, double scl, double mag){
Vec3 v = sector.rect.project(x, y);
return (float)noise.octaveNoise3D(octaves, falloff, 1f / scl, v.x, v.y, v.z) * (float)mag;
return (float)Simplex.noise3d(0, octaves, falloff, 1f / scl, v.x, v.y, v.z) * (float)mag;
}
/** @return the scaling factor for sector rects. */

View File

@ -18,6 +18,8 @@ import mindustry.world.*;
import static mindustry.Vars.*;
public class SerpuloPlanetGenerator extends PlanetGenerator{
static final int seed = 0;
BaseGenerator basegen = new BaseGenerator();
float scl = 5f;
float waterOffset = 0.07f;
@ -55,7 +57,7 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
float rawHeight(Vec3 position){
position = Tmp.v33.set(position).scl(scl);
return (Mathf.pow((float)noise.octaveNoise3D(7, 0.5f, 1f/3f, position.x, position.y, position.z), 2.3f) + waterOffset) / (1f + waterOffset);
return (Mathf.pow((float)Simplex.noise3d(seed, 7, 0.5f, 1f/3f, position.x, position.y, position.z), 2.3f) + waterOffset) / (1f + waterOffset);
}
@Override
@ -114,7 +116,7 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
tile.floor = getBlock(position);
tile.block = tile.floor.asFloor().wall;
if(RidgedPerlin.noise3d(1, position.x, position.y, position.z, 2, 22) > 0.31){
if(Ridged.noise3d(1, position.x, position.y, position.z, 2, 22) > 0.31){
tile.block = Blocks.air;
}
}
@ -125,12 +127,12 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
position = Tmp.v33.set(position).scl(scl);
float rad = scl;
float temp = Mathf.clamp(Math.abs(position.y * 2f) / (rad));
float tnoise = (float)noise.octaveNoise3D(7, 0.56, 1f/3f, position.x, position.y + 999f, position.z);
float tnoise = (float)Simplex.noise3d(seed, 7, 0.56, 1f/3f, position.x, position.y + 999f, position.z);
temp = Mathf.lerp(temp, tnoise, 0.5f);
height *= 1.2f;
height = Mathf.clamp(height);
float tar = (float)noise.octaveNoise3D(4, 0.55f, 1f/2f, position.x, position.y + 999f, position.z) * 0.3f + Tmp.v31.dst(0, 0, 1f) * 0.2f;
float tar = (float)Simplex.noise3d(seed, 4, 0.55f, 1f/2f, position.x, position.y + 999f, position.z) * 0.3f + Tmp.v31.dst(0, 0, 1f) * 0.2f;
Block res = arr[Mathf.clamp((int)(temp * arr.length), 0, arr[0].length - 1)][Mathf.clamp((int)(height * arr[0].length), 0, arr[0].length - 1)];
if(tar > 0.5f){
@ -143,7 +145,7 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
@Override
protected float noise(float x, float y, double octaves, double falloff, double scl, double mag){
Vec3 v = sector.rect.project(x, y).scl(5f);
return (float)noise.octaveNoise3D(octaves, falloff, 1f / scl, v.x, v.y, v.z) * (float)mag;
return (float)Simplex.noise3d(seed, octaves, falloff, 1f / scl, v.x, v.y, v.z) * (float)mag;
}
@Override
@ -250,15 +252,15 @@ public class SerpuloPlanetGenerator extends PlanetGenerator{
float scl = 1f;
float addscl = 1.3f;
if(noise.octaveNoise3D(2, 0.5, scl, sector.tile.v.x, sector.tile.v.y, sector.tile.v.z)*nmag + poles > 0.25f*addscl){
if(Simplex.noise3d(seed, 2, 0.5, scl, sector.tile.v.x, sector.tile.v.y, sector.tile.v.z)*nmag + poles > 0.25f*addscl){
ores.add(Blocks.oreCoal);
}
if(noise.octaveNoise3D(2, 0.5, scl, sector.tile.v.x + 1, sector.tile.v.y, sector.tile.v.z)*nmag + poles > 0.5f*addscl){
if(Simplex.noise3d(seed, 2, 0.5, scl, sector.tile.v.x + 1, sector.tile.v.y, sector.tile.v.z)*nmag + poles > 0.5f*addscl){
ores.add(Blocks.oreTitanium);
}
if(noise.octaveNoise3D(2, 0.5, scl, sector.tile.v.x + 2, sector.tile.v.y, sector.tile.v.z)*nmag + poles > 0.7f*addscl){
if(Simplex.noise3d(seed, 2, 0.5, scl, sector.tile.v.x + 2, sector.tile.v.y, sector.tile.v.z)*nmag + poles > 0.7f*addscl){
ores.add(Blocks.oreThorium);
}

View File

@ -1,6 +1,9 @@
package mindustry.mod;
import arc.struct.*;
import mindustry.world.blocks.environment.*;
import mindustry.world.blocks.payloads.*;
/** Generated class. Maps simple class names to concrete classes. For use in JSON mods. */
@SuppressWarnings("deprecation")
public class ClassMap{
@ -171,20 +174,20 @@ public class ClassMap{
classes.put("OreBlock", mindustry.world.blocks.environment.OreBlock.class);
classes.put("OverlayFloor", mindustry.world.blocks.environment.OverlayFloor.class);
classes.put("Prop", mindustry.world.blocks.environment.Prop.class);
classes.put("SeaBush", mindustry.world.blocks.environment.SeaBush.class);
classes.put("Seaweed", mindustry.world.blocks.environment.Seaweed.class);
classes.put("Bush", Bush.class);
classes.put("WavingProp", WavingProp.class);
classes.put("ShallowLiquid", mindustry.world.blocks.environment.ShallowLiquid.class);
classes.put("SpawnBlock", mindustry.world.blocks.environment.SpawnBlock.class);
classes.put("StaticCoralWall", mindustry.world.blocks.environment.StaticCoralWall.class);
classes.put("StaticClusterWall", StaticClusterWall.class);
classes.put("StaticTree", mindustry.world.blocks.environment.StaticTree.class);
classes.put("StaticWall", mindustry.world.blocks.environment.StaticWall.class);
classes.put("TreeBlock", mindustry.world.blocks.environment.TreeBlock.class);
classes.put("WallOreBlock", mindustry.world.blocks.environment.WallOreBlock.class);
classes.put("WobbleProp", mindustry.world.blocks.environment.WobbleProp.class);
classes.put("BlockLoader", mindustry.world.blocks.experimental.BlockLoader.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("BlockLoader", BlockLoader.class);
classes.put("BlockLoaderBuild", BlockLoader.BlockLoaderBuild.class);
classes.put("BlockUnloader", BlockUnloader.class);
classes.put("BlockUnloaderBuild", BlockUnloader.BlockUnloaderBuild.class);
classes.put("LegacyBlock", mindustry.world.blocks.legacy.LegacyBlock.class);
classes.put("LegacyMechPad", mindustry.world.blocks.legacy.LegacyMechPad.class);
classes.put("LegacyMechPadBuild", mindustry.world.blocks.legacy.LegacyMechPad.LegacyMechPadBuild.class);
@ -235,7 +238,7 @@ public class ClassMap{
classes.put("PayloadSource", mindustry.world.blocks.payloads.PayloadSource.class);
classes.put("PayloadSourceBuild", mindustry.world.blocks.payloads.PayloadSource.PayloadSourceBuild.class);
classes.put("PayloadVoid", mindustry.world.blocks.payloads.PayloadVoid.class);
classes.put("BlockLoaderBuild", mindustry.world.blocks.payloads.PayloadVoid.BlockLoaderBuild.class);
classes.put("BlockLoaderBuild", PayloadVoid.PayloadVoidBuild.class);
classes.put("UnitPayload", mindustry.world.blocks.payloads.UnitPayload.class);
classes.put("Battery", mindustry.world.blocks.power.Battery.class);
classes.put("BatteryBuild", mindustry.world.blocks.power.Battery.BatteryBuild.class);

View File

@ -752,8 +752,8 @@ public class ContentParser{
var out = ClassMap.classes.get(!base.isEmpty() && Character.isLowerCase(base.charAt(0)) ? Strings.capitalize(base) : base);
if(out != null) return (Class<T>)out;
//try to resolve it as a raw class name if it's allowed
if(base.indexOf('.') != -1 && Scripts.allowClass(base)){
//try to resolve it as a raw class name
if(base.indexOf('.') != -1){
try{
return (Class<T>)Class.forName(base);
}catch(Exception ignored){

View File

@ -22,22 +22,12 @@ import java.util.*;
import java.util.regex.*;
public class Scripts implements Disposable{
private static final Seq<String> blacklist = Seq.with(".net.", "java.net", "files", "reflect", "javax", "rhino", "file", "channels", "jdk",
"runtime", "util.os", "rmi", "security", "org.", "sun.", "beans", "sql", "http", "exec", "compiler", "process", "system",
".awt", "socket", "classloader", "oracle", "invoke", "java.util.function", "java.util.stream", "org.", "mod.classmap");
private static final Seq<String> whitelist = Seq.with("mindustry.net", "netserver", "netclient", "com.sun.proxy.$proxy", "jdk.proxy", "mindustry.gen.",
"mindustry.logic.", "mindustry.async.", "saveio", "systemcursor", "filetreeinitevent", "asyncexecutor");
private final Context context;
private final Scriptable scope;
private boolean errored;
LoadedMod currentMod = null;
public static boolean allowClass(String type){
return !blacklist.contains(t -> type.toLowerCase(Locale.ROOT).contains(t)) || whitelist.contains(t -> type.toLowerCase(Locale.ROOT).contains(t));
}
public Scripts(){
Time.mark();

View File

@ -174,21 +174,12 @@ public class ModsDialog extends BaseDialog{
dialog.hide();
platform.showMultiFileChooser(file -> {
Runnable go = () -> {
try{
mods.importMod(file);
setup();
}catch(IOException e){
ui.showException(e);
e.printStackTrace();
}
};
//show unsafe jar file warning
if(file.extEquals("jar")){
ui.showConfirm("@warning", "@mod.jarwarn", go);
}else{
go.run();
try{
mods.importMod(file);
setup();
}catch(IOException e){
ui.showException(e);
Log.err(e);
}
}, "zip", "jar");
}).margin(12f);
@ -529,10 +520,7 @@ public class ModsDialog extends BaseDialog{
private void githubImportMod(String repo, boolean isJava){
if(isJava){
ui.showConfirm("@warning", "@mod.jarwarn", () -> {
ui.loadfrag.show();
githubImportJavaMod(repo);
});
githubImportJavaMod(repo);
}else{
ui.loadfrag.show();
Core.net.httpGet(ghApi + "/repos/" + repo, res -> {

View File

@ -92,6 +92,8 @@ public class ConstructBlock extends Block{
Fx.placeBlock.at(tile.drawx(), tile.drawy(), block.size);
if(shouldPlay()) Sounds.place.at(tile, calcPitch(true));
Events.fire(new BlockBuildEndEvent(tile, builder, team, false, config));
}
static boolean shouldPlay(){
@ -123,8 +125,6 @@ public class ConstructBlock extends Block{
if(tile.build != null){
tile.build.placed();
}
Events.fire(new BlockBuildEndEvent(tile, builder, team, false, config));
}
@Override
@ -259,7 +259,9 @@ public class ConstructBlock extends Block{
if(progress >= 1f || state.rules.infiniteResources){
if(lastBuilder == null) lastBuilder = builder;
constructed(tile, current, lastBuilder, (byte)rotation, builder.team, config);
if(!net.client()){
constructed(tile, current, lastBuilder, (byte)rotation, builder.team, config);
}
}
}

View File

@ -324,7 +324,7 @@ public class MassDriver extends Block{
}
protected boolean shooterValid(Building other){
return other instanceof MassDriverBuild entity && other.consValid() && entity.block == block && entity.link == pos() && within(other, range);
return other instanceof MassDriverBuild entity && other.isValid() && other.consValid() && entity.block == block && entity.link == pos() && within(other, range);
}
protected boolean linkValid(){

View File

@ -0,0 +1,14 @@
package mindustry.world.blocks.experimental;
@Deprecated
public class BlockForge extends mindustry.world.blocks.payloads.BlockForge{
public BlockForge(String name){
super(name);
}
@Deprecated
public class BlockForgeBuild extends mindustry.world.blocks.payloads.BlockForge.BlockForgeBuild{
}
}

View File

@ -1,148 +1,14 @@
package mindustry.world.blocks.experimental;
import arc.*;
import arc.graphics.g2d.*;
import arc.util.*;
import mindustry.entities.units.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.type.*;
import mindustry.ui.*;
import mindustry.world.blocks.payloads.*;
import static mindustry.Vars.*;
public class BlockLoader extends PayloadBlock{
public final int timerLoad = timers++;
public float loadTime = 2f;
public int itemsLoaded = 5;
public float liquidsLoaded = 5f;
public int maxBlockSize = 2;
@Deprecated
public class BlockLoader extends mindustry.world.blocks.payloads.BlockLoader{
public BlockLoader(String name){
super(name);
hasItems = true;
itemCapacity = 25;
//liquidCapacity = 25;
update = true;
outputsPayload = true;
size = 3;
rotate = true;
}
@Override
public TextureRegion[] icons(){
return new TextureRegion[]{region, inRegion, outRegion, topRegion};
}
@Deprecated
public class BlockLoaderBuild extends mindustry.world.blocks.payloads.BlockLoader.BlockLoaderBuild{
@Override
public boolean outputsItems(){
return false;
}
@Override
public void setBars(){
super.setBars();
bars.add("progress", (BlockLoaderBuild entity) -> new Bar(() -> Core.bundle.format("bar.items", entity.payload == null ? 0 : entity.payload.build.items.total()), () -> Pal.items, entity::fraction));
}
@Override
public void drawRequestRegion(BuildPlan req, Eachable<BuildPlan> list){
Draw.rect(region, req.drawx(), req.drawy());
Draw.rect(inRegion, req.drawx(), req.drawy(), req.rotation * 90);
Draw.rect(outRegion, req.drawx(), req.drawy(), req.rotation * 90);
Draw.rect(topRegion, req.drawx(), req.drawy());
}
public class BlockLoaderBuild extends PayloadBlockBuild<BuildPayload>{
@Override
public boolean acceptPayload(Building source, Payload payload){
return super.acceptPayload(source, payload) &&
(payload instanceof BuildPayload build) &&
((build.build.block.hasItems && build.block().unloadable && build.block().itemCapacity >= 10 && build.block().size <= maxBlockSize)/* ||
((BlockPayload)payload).entity.block().hasLiquids && ((BlockPayload)payload).block().liquidCapacity >= 10f)*/);
}
@Override
public boolean acceptItem(Building source, Item item){
return items.total() < itemCapacity;
}
@Override
public void draw(){
Draw.rect(region, x, y);
//draw input
boolean fallback = true;
for(int i = 0; i < 4; i++){
if(blends(i) && i != rotation){
Draw.rect(inRegion, x, y, (i * 90) - 180);
fallback = false;
}
}
if(fallback) Draw.rect(inRegion, x, y, rotation * 90);
Draw.rect(outRegion, x, y, rotdeg());
Draw.z(Layer.blockOver);
drawPayload();
Draw.z(Layer.blockOver + 0.1f);
Draw.rect(topRegion, x, y);
}
@Override
public void updateTile(){
if(shouldExport()){
moveOutPayload();
}else if(moveInPayload()){
//load up items
if(payload.block().hasItems && items.any()){
if(efficiency() > 0.01f && timer(timerLoad, loadTime / efficiency())){
//load up items a set amount of times
for(int j = 0; j < itemsLoaded && items.any(); j++){
for(int i = 0; i < items.length(); i++){
if(items.get(i) > 0){
Item item = content.item(i);
if(payload.build.acceptItem(payload.build, item)){
payload.build.handleItem(payload.build, item);
items.remove(item, 1);
break;
}
}
}
}
}
}
//load up liquids (disabled)
/*
if(payload.block().hasLiquids && liquids.total() >= 0.001f){
Liquid liq = liquids.current();
float total = liquids.currentAmount();
float flow = Math.min(Math.min(liquidsLoaded * delta(), payload.block().liquidCapacity - payload.entity.liquids.get(liq) - 0.0001f), total);
if(payload.entity.acceptLiquid(payload.entity, liq, flow)){
payload.entity.liquids.add(liq, flow);
liquids.remove(liq, flow);
}
}*/
}
}
public float fraction(){
return payload == null ? 0f : payload.build.items.total() / (float)payload.build.block.itemCapacity;
}
public boolean shouldExport(){
return payload != null &&
((payload.block().hasLiquids && payload.build.liquids.total() >= payload.block().liquidCapacity - 0.001f) ||
(payload.block().hasItems && payload.build.items.total() >= payload.block().itemCapacity));
}
}
}

View File

@ -1,67 +1,14 @@
package mindustry.world.blocks.experimental;
import mindustry.gen.*;
import mindustry.type.*;
import static mindustry.Vars.*;
public class BlockUnloader extends BlockLoader{
@Deprecated
public class BlockUnloader extends mindustry.world.blocks.payloads.BlockUnloader{
public BlockUnloader(String name){
super(name);
}
@Override
public boolean outputsItems(){
return true;
}
@Deprecated
public class BlockUnloaderBuild extends mindustry.world.blocks.payloads.BlockUnloader.BlockUnloaderBuild{
@Override
public boolean rotatedOutput(int x, int y){
return false;
}
public class BlockUnloaderBuild extends BlockLoaderBuild{
@Override
public boolean acceptItem(Building source, Item item){
return false;
}
@Override
public void updateTile(){
if(shouldExport()){
moveOutPayload();
}else if(moveInPayload()){
//load up items
if(payload.block().hasItems && !full()){
if(efficiency() > 0.01f && timer(timerLoad, loadTime / efficiency())){
//load up items a set amount of times
for(int j = 0; j < itemsLoaded && !full(); j++){
for(int i = 0; i < items.length(); i++){
if(payload.build.items.get(i) > 0){
Item item = content.item(i);
payload.build.items.remove(item, 1);
items.add(item, 1);
break;
}
}
}
}
}
}
dump();
}
public boolean full(){
return items.total() >= itemCapacity;
}
@Override
public boolean shouldExport(){
return payload != null && (payload.block().hasItems && payload.build.items.empty());
}
}
}

View File

@ -0,0 +1,147 @@
package mindustry.world.blocks.payloads;
import arc.*;
import arc.graphics.g2d.*;
import arc.util.*;
import mindustry.entities.units.*;
import mindustry.gen.*;
import mindustry.graphics.*;
import mindustry.type.*;
import mindustry.ui.*;
import static mindustry.Vars.*;
public class BlockLoader extends PayloadBlock{
public final int timerLoad = timers++;
public float loadTime = 2f;
public int itemsLoaded = 5;
public float liquidsLoaded = 5f;
public int maxBlockSize = 2;
public BlockLoader(String name){
super(name);
hasItems = true;
itemCapacity = 25;
//liquidCapacity = 25;
update = true;
outputsPayload = true;
size = 3;
rotate = true;
}
@Override
public TextureRegion[] icons(){
return new TextureRegion[]{region, inRegion, outRegion, topRegion};
}
@Override
public boolean outputsItems(){
return false;
}
@Override
public void setBars(){
super.setBars();
bars.add("progress", (BlockLoaderBuild entity) -> new Bar(() -> Core.bundle.format("bar.items", entity.payload == null ? 0 : entity.payload.build.items.total()), () -> Pal.items, entity::fraction));
}
@Override
public void drawRequestRegion(BuildPlan req, Eachable<BuildPlan> list){
Draw.rect(region, req.drawx(), req.drawy());
Draw.rect(inRegion, req.drawx(), req.drawy(), req.rotation * 90);
Draw.rect(outRegion, req.drawx(), req.drawy(), req.rotation * 90);
Draw.rect(topRegion, req.drawx(), req.drawy());
}
public class BlockLoaderBuild extends PayloadBlockBuild<BuildPayload>{
@Override
public boolean acceptPayload(Building source, Payload payload){
return super.acceptPayload(source, payload) &&
(payload instanceof BuildPayload build) &&
((build.build.block.hasItems && build.block().unloadable && build.block().itemCapacity >= 10 && build.block().size <= maxBlockSize)/* ||
((BlockPayload)payload).entity.block().hasLiquids && ((BlockPayload)payload).block().liquidCapacity >= 10f)*/);
}
@Override
public boolean acceptItem(Building source, Item item){
return items.total() < itemCapacity;
}
@Override
public void draw(){
Draw.rect(region, x, y);
//draw input
boolean fallback = true;
for(int i = 0; i < 4; i++){
if(blends(i) && i != rotation){
Draw.rect(inRegion, x, y, (i * 90) - 180);
fallback = false;
}
}
if(fallback) Draw.rect(inRegion, x, y, rotation * 90);
Draw.rect(outRegion, x, y, rotdeg());
Draw.z(Layer.blockOver);
drawPayload();
Draw.z(Layer.blockOver + 0.1f);
Draw.rect(topRegion, x, y);
}
@Override
public void updateTile(){
if(shouldExport()){
moveOutPayload();
}else if(moveInPayload()){
//load up items
if(payload.block().hasItems && items.any()){
if(efficiency() > 0.01f && timer(timerLoad, loadTime / efficiency())){
//load up items a set amount of times
for(int j = 0; j < itemsLoaded && items.any(); j++){
for(int i = 0; i < items.length(); i++){
if(items.get(i) > 0){
Item item = content.item(i);
if(payload.build.acceptItem(payload.build, item)){
payload.build.handleItem(payload.build, item);
items.remove(item, 1);
break;
}
}
}
}
}
}
//load up liquids (disabled)
/*
if(payload.block().hasLiquids && liquids.total() >= 0.001f){
Liquid liq = liquids.current();
float total = liquids.currentAmount();
float flow = Math.min(Math.min(liquidsLoaded * delta(), payload.block().liquidCapacity - payload.entity.liquids.get(liq) - 0.0001f), total);
if(payload.entity.acceptLiquid(payload.entity, liq, flow)){
payload.entity.liquids.add(liq, flow);
liquids.remove(liq, flow);
}
}*/
}
}
public float fraction(){
return payload == null ? 0f : payload.build.items.total() / (float)payload.build.block.itemCapacity;
}
public boolean shouldExport(){
return payload != null &&
((payload.block().hasLiquids && payload.build.liquids.total() >= payload.block().liquidCapacity - 0.001f) ||
(payload.block().hasItems && payload.build.items.total() >= payload.block().itemCapacity));
}
}
}

View File

@ -0,0 +1,67 @@
package mindustry.world.blocks.payloads;
import mindustry.gen.*;
import mindustry.type.*;
import static mindustry.Vars.*;
public class BlockUnloader extends BlockLoader{
public BlockUnloader(String name){
super(name);
}
@Override
public boolean outputsItems(){
return true;
}
@Override
public boolean rotatedOutput(int x, int y){
return false;
}
public class BlockUnloaderBuild extends BlockLoaderBuild{
@Override
public boolean acceptItem(Building source, Item item){
return false;
}
@Override
public void updateTile(){
if(shouldExport()){
moveOutPayload();
}else if(moveInPayload()){
//load up items
if(payload.block().hasItems && !full()){
if(efficiency() > 0.01f && timer(timerLoad, loadTime / efficiency())){
//load up items a set amount of times
for(int j = 0; j < itemsLoaded && !full(); j++){
for(int i = 0; i < items.length(); i++){
if(payload.build.items.get(i) > 0){
Item item = content.item(i);
payload.build.items.remove(item, 1);
items.add(item, 1);
break;
}
}
}
}
}
}
dump();
}
public boolean full(){
return items.total() >= itemCapacity;
}
@Override
public boolean shouldExport(){
return payload != null && (payload.block().hasItems && payload.build.items.empty());
}
}
}

View File

@ -184,6 +184,7 @@ public class PayloadMassDriver extends PayloadBlock{
if(current != null &&
!(
current instanceof PayloadDriverBuild entity &&
current.isValid() &&
entity.consValid() && entity.block == block &&
entity.link == pos() && within(current, range)
)){

View File

@ -29,7 +29,7 @@ public class PayloadVoid extends PayloadBlock{
return new TextureRegion[]{region, topRegion};
}
public class BlockLoaderBuild extends PayloadBlockBuild<Payload>{
public class PayloadVoidBuild extends PayloadBlockBuild<Payload>{
@Override
public void draw(){

View File

@ -61,6 +61,8 @@ public class ItemLiquidGenerator extends PowerGenerator{
@Override
public void init(){
emitLight = true;
lightRadius = 65f * size;
if(!defaults){
setDefaults();
}

View File

@ -48,7 +48,7 @@ task dist(type: Jar, dependsOn: configurations.runtimeClasspath){
}
}
if(!project.ext.hasSprites()){
if(!project.ext.hasSprites() && System.getenv("JITPACK") != "true"){
println "Scheduling sprite packing."
run.dependsOn ":tools:pack"
dist.dependsOn ":tools:pack"

View File

@ -1,6 +1,5 @@
org.gradle.daemon=true
#--illegal-access=permit
org.gradle.jvmargs=-Xms256m -Xmx1024m
org.gradle.jvmargs=-Xms256m -Xmx1024m --illegal-access=permit
# Don't recompute annotations if sources haven't been changed
kapt.incremental.apt = true
# Multithreaded
@ -9,4 +8,6 @@ kapt.use.worker.api=true
kapt.include.compile.classpath=false
# I don't need to use the kotlin stdlib yet, so remove it to prevent extra bloat & method count issues
kotlin.stdlib.default.dependency=false
archash=3926b785320fea0cd9ca597f6bfa9071263a5464
#needed for android compilation
android.useAndroidX=true
archash=07ced971f4c8b8b5a61aa3a84b29c90aa497cb48

Binary file not shown.

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

31
gradlew vendored
View File

@ -82,6 +82,7 @@ esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
@ -129,6 +130,7 @@ fi
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
@ -154,19 +156,19 @@ if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
i=`expr $i + 1`
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
@ -175,14 +177,9 @@ save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

25
gradlew.bat vendored
View File

@ -29,6 +29,9 @@ if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@ -37,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@ -51,7 +54,7 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@ -61,28 +64,14 @@ echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell

View File

@ -1,4 +1,9 @@
jdk:
- openjdk16
before_install:
- wget https://github.com/sormuras/bach/raw/master/install-jdk.sh
- source install-jdk.sh --feature 14
- source install-jdk.sh --feature 16
- jshell --version
install:
- ./gradlew publishToMavenLocal
- sed -i 's/ --illegal-access=permit//' gradle.properties #remove extra flags after compilation

View File

@ -2,7 +2,6 @@ package mindustry.server;
import arc.*;
import arc.backend.headless.*;
import arc.files.*;
import arc.util.*;
import mindustry.*;
import mindustry.core.*;
@ -44,15 +43,6 @@ public class ServerLauncher implements ApplicationListener{
loadLocales = false;
headless = true;
Fi plugins = Core.settings.getDataDirectory().child("plugins");
if(plugins.isDirectory() && plugins.list().length > 0 && !plugins.sibling("mods").exists()){
warn("[IMPORTANT NOTICE] &lrPlugins have been detected.&ly Automatically moving all contents of the plugin folder into the 'mods' folder. The original folder will not be removed; please do so manually.");
plugins.sibling("mods").mkdirs();
for(Fi file : plugins.list()){
file.copyTo(plugins.sibling("mods"));
}
}
Vars.loadSettings();
Vars.init();
content.createBaseContent();

View File

@ -13,8 +13,5 @@
},
{
"address": "mindurka.tk:9999"
},
{
"address": "mindustrypvp.ml:6000"
}
]

View File

@ -1,5 +1,5 @@
if(JavaVersion.current().ordinal() < JavaVersion.VERSION_14.ordinal()){
throw new GradleException("!!! YOU MUST USE JAVA 14 OR ABOVE TO COMPILE AND RUN MINDUSTRY !!! Read the README. Your version: ${System.properties["java.version"]}")
if(JavaVersion.current().ordinal() < JavaVersion.VERSION_16.ordinal()){
throw new Exception("!!! YOU MUST USE JAVA 16 OR ABOVE TO COMPILE AND RUN MINDUSTRY !!! Read the README. Your version: ${System.properties["java.version"]}")
}
include 'desktop', 'core', 'server', 'ios', 'annotations', 'tools', 'tests'

View File

@ -1,10 +1,12 @@
import arc.*;
import arc.backend.headless.*;
import arc.files.*;
import arc.func.*;
import arc.math.*;
import arc.math.geom.*;
import arc.struct.*;
import arc.util.*;
import arc.util.io.*;
import arc.util.serialization.*;
import arc.util.serialization.JsonValue.*;
import mindustry.*;
@ -16,21 +18,36 @@ import mindustry.entities.units.*;
import mindustry.game.*;
import mindustry.gen.*;
import mindustry.io.*;
import mindustry.io.SaveIO.*;
import mindustry.maps.*;
import mindustry.mod.*;
import mindustry.mod.Mods.*;
import mindustry.net.Net;
import mindustry.type.*;
import mindustry.world.*;
import mindustry.world.blocks.storage.*;
import org.junit.jupiter.api.*;
import org.junit.jupiter.params.*;
import org.junit.jupiter.params.provider.*;
import java.nio.*;
import static mindustry.Vars.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.DynamicTest.*;
public class ApplicationTests{
static Map testMap;
static boolean initialized;
//core/assets
static final Fi testDataFolder = new Fi("../../tests/build/test_data");
@BeforeAll
static void launchApplication(){
public static void launchApplication(){
launchApplication(true);
}
public static void launchApplication(boolean clear){
//only gets called once
if(initialized) return;
initialized = true;
@ -43,6 +60,12 @@ public class ApplicationTests{
ApplicationCore core = new ApplicationCore(){
@Override
public void setup(){
//clear older data
if(clear){
ApplicationTests.testDataFolder.deleteDirectory();
}
Core.settings.setDataDirectory(testDataFolder);
headless = true;
net = new Net(null);
tree = new FileTree();
@ -55,12 +78,26 @@ public class ApplicationTests{
}
};
content.createBaseContent();
mods.loadScripts();
content.createModContent();
add(logic = new Logic());
add(netServer = new NetServer());
content.init();
mods.eachClass(Mod::init);
if(mods.hasContentErrors()){
for(LoadedMod mod : mods.list()){
if(mod.hasContentErrors()){
for(Content cont : mod.erroredContent){
throw new RuntimeException("error in file: " + cont.minfo.sourceFile.path(), cont.minfo.baseError);
}
}
}
}
}
@Override
@ -96,6 +133,55 @@ public class ApplicationTests{
state.set(State.menu);
}
@ParameterizedTest
@NullSource
@ValueSource(strings = {
"asd asd asd asd asdagagasasjakbgeah;jwrej 23424234",
"这个服务器可以用自己的语言说话"
})
void writeStringTest(String string){
ByteBuffer buffer = ByteBuffer.allocate(500);
TypeIO.writeString(buffer, string);
buffer.position(0);
assertEquals(TypeIO.readString(buffer), string);
}
@Test
void writeRules(){
ByteBuffer buffer = ByteBuffer.allocate(500);
Rules rules = new Rules();
rules.attackMode = true;
rules.buildSpeedMultiplier = 99f;
TypeIO.writeRules(new Writes(new ByteBufferOutput(buffer)), rules);
buffer.position(0);
Rules res = TypeIO.readRules(new Reads(new ByteBufferInput(buffer)));
assertEquals(rules.buildSpeedMultiplier, res.buildSpeedMultiplier);
assertEquals(rules.attackMode, res.attackMode);
}
@Test
void writeRules2(){
Rules rules = new Rules();
rules.attackMode = true;
rules.tags.put("blah", "bleh");
rules.buildSpeedMultiplier = 99.1f;
String str = JsonIO.write(rules);
Rules res = JsonIO.read(Rules.class, str);
assertEquals(rules.buildSpeedMultiplier, res.buildSpeedMultiplier);
assertEquals(rules.attackMode, res.attackMode);
assertEquals(rules.tags.get("blah"), res.tags.get("blah"));
String str2 = JsonIO.write(new Rules(){{
attackMode = true;
}});
Log.info(str2);
}
@Test
void serverListJson(){
String[] files = {"servers.json", "servers_be.json", "servers_v6.json"};
@ -730,6 +816,83 @@ public class ApplicationTests{
}
}
@TestFactory
DynamicTest[] testSectorValidity(){
Seq<DynamicTest> out = new Seq<>();
if(world == null) world = new World();
for(SectorPreset zone : content.sectors()){
out.add(dynamicTest(zone.name, () -> {
Time.setDeltaProvider(() -> 1f);
logic.reset();
try{
world.loadGenerator(zone.generator.map.width, zone.generator.map.height, zone.generator::generate);
}catch(SaveException e){
//fails randomly and I don't care about fixing it
e.printStackTrace();
return;
}
zone.rules.get(state.rules);
ObjectSet<Item> resources = new ObjectSet<>();
boolean hasSpawnPoint = false;
for(Tile tile : world.tiles){
if(tile.drop() != null){
resources.add(tile.drop());
}
if(tile.block() instanceof CoreBlock && tile.team() == state.rules.defaultTeam){
hasSpawnPoint = true;
}
}
Seq<SpawnGroup> spawns = state.rules.spawns;
int bossWave = 0;
if(state.rules.winWave > 0){
bossWave = state.rules.winWave;
}else{
outer:
for(int i = 1; i <= 1000; i++){
for(SpawnGroup spawn : spawns){
if(spawn.effect == StatusEffects.boss && spawn.getSpawned(i) > 0){
bossWave = i;
break outer;
}
}
}
}
if(state.rules.attackMode){
bossWave = 100;
}else{
assertNotEquals(0, bossWave, "Sector doesn't have a boss wave.");
}
//TODO check for difficulty?
for(int i = 1; i <= bossWave; i++){
int total = 0;
for(SpawnGroup spawn : spawns){
total += spawn.getSpawned(i);
}
assertNotEquals(0, total, "Sector " + zone + " has no spawned enemies at wave " + i);
//TODO this is flawed and needs to be changed later
//assertTrue(total < 75, "Sector spawns too many enemies at wave " + i + " (" + total + ")");
}
assertEquals(1, Team.sharded.cores().size, "Sector must have one core: " + zone);
assertTrue(Team.sharded.core().items.total() < 1000, "Sector must not have starting resources: " + zone);
assertTrue(hasSpawnPoint, "Sector \"" + zone.name + "\" has no spawn points.");
assertTrue(spawner.countSpawns() > 0 || (state.rules.attackMode && state.rules.waveTeam.data().hasCore()), "Sector \"" + zone.name + "\" has no enemy spawn points: " + spawner.countSpawns());
}));
}
return out.toArray(DynamicTest.class);
}
void initBuilding(){
createMap();

View File

@ -0,0 +1,35 @@
import arc.*;
import arc.Net.*;
import arc.util.io.*;
import mindustry.*;
import org.junit.jupiter.api.*;
import java.io.*;
import static org.junit.jupiter.api.Assertions.*;
public class GenericModTest{
/** grabs a mod and puts it in the mod folder */
static void grabMod(String url){
//clear older mods
ApplicationTests.testDataFolder.deleteDirectory();
Core.net = new Net();
Core.net.setBlock(true);
Core.net.http(new HttpRequest().url(url).method(HttpMethod.GET), httpResponse -> {
try{
ApplicationTests.testDataFolder.child("mods").child("test_mod." + (url.endsWith("jar") ? "jar" : "zip")).writeBytes(Streams.copyBytes(httpResponse.getResultAsStream()));
}catch(IOException e){
Assertions.fail(e);
}
}, Assertions::fail);
ApplicationTests.launchApplication(false);
}
static void checkExistence(String modName){
assertNotEquals(Vars.mods, null);
assertNotEquals(Vars.mods.list().size, 0, "At least one mod must be loaded.");
assertEquals(Vars.mods.list().first().name, modName, modName + " must be loaded.");
}
}

View File

@ -1,63 +0,0 @@
import arc.util.*;
import arc.util.io.*;
import mindustry.game.*;
import mindustry.io.*;
import org.junit.jupiter.api.*;
import org.junit.jupiter.params.*;
import org.junit.jupiter.params.provider.*;
import java.nio.*;
import static org.junit.jupiter.api.Assertions.*;
public class IOTests{
@ParameterizedTest
@NullSource
@ValueSource(strings = {
"asd asd asd asd asdagagasasjakbgeah;jwrej 23424234",
"这个服务器可以用自己的语言说话"
})
void writeStringTest(String string){
ByteBuffer buffer = ByteBuffer.allocate(500);
TypeIO.writeString(buffer, string);
buffer.position(0);
assertEquals(TypeIO.readString(buffer), string);
}
@Test
void writeRules(){
ByteBuffer buffer = ByteBuffer.allocate(500);
Rules rules = new Rules();
rules.attackMode = true;
rules.buildSpeedMultiplier = 99f;
TypeIO.writeRules(new Writes(new ByteBufferOutput(buffer)), rules);
buffer.position(0);
Rules res = TypeIO.readRules(new Reads(new ByteBufferInput(buffer)));
assertEquals(rules.buildSpeedMultiplier, res.buildSpeedMultiplier);
assertEquals(rules.attackMode, res.attackMode);
}
@Test
void writeRules2(){
Rules rules = new Rules();
rules.attackMode = true;
rules.tags.put("blah", "bleh");
rules.buildSpeedMultiplier = 99.1f;
String str = JsonIO.write(rules);
Rules res = JsonIO.read(Rules.class, str);
assertEquals(rules.buildSpeedMultiplier, res.buildSpeedMultiplier);
assertEquals(rules.attackMode, res.attackMode);
assertEquals(rules.tags.get("blah"), res.tags.get("blah"));
String str2 = JsonIO.write(new Rules(){{
attackMode = true;
}});
Log.info(str2);
}
}

View File

@ -0,0 +1,39 @@
import mindustry.*;
import mindustry.world.*;
import mindustry.world.meta.*;
import org.junit.jupiter.api.*;
import static mindustry.Vars.*;
import static org.junit.jupiter.api.Assertions.*;
//grabs a betamindy release and makes sure it initializes correctly
//this mod was chosen because:
//- it is one of the top java mods on the browser
//- it uses a variety of mindustry classes
//- it is popular enough to cause significant amounts of crashes when something breaks
//- I have some familiarity with its codebase
public class ModTestBM extends GenericModTest{
@Test
public void begin(){
grabMod("https://github.com/sk7725/BetaMindy/releases/download/v0.955/BetaMindy.jar");
checkExistence("betamindy");
Block type = Vars.content.blocks().find(u -> u.name.equals("betamindy-piston"));
assertNotNull(type, "A mod block must be loaded.");
assertSame(type.buildVisibility, BuildVisibility.shown, "A mod block must be buildable.");
world.loadMap(ApplicationTests.testMap);
Tile t = world.tile(3, 3);
t.setBlock(type);
//check for crash
t.build.update();
assertTrue(t.build.health > 0, "Block must be spawned and alive.");
assertSame(t.build.block, type, "Block must be spawned and alive.");
}
}

View File

@ -0,0 +1,40 @@
import arc.util.*;
import mindustry.*;
import mindustry.gen.*;
import mindustry.type.*;
import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.*;
//grabs a version-locked exotic-mod commit and makes sure its content is parsed correctly
//this mod was chosen because:
//- it is written solely in (h)json
//- it is probably the mod with the most json, and as such covers a lot of classes
//- it is popular enough in the mod browser
//- I am somewhat familiar with its files & the type of content it adds
public class ModTestExotic extends GenericModTest{
@Test
public void begin(){
grabMod("https://github.com/BlueWolf3682/Exotic-Mod/archive/08c861398ac9c3d1292132f9a110e17e06294a90.zip");
checkExistence("exotic-mod");
UnitType type = Vars.content.units().find(u -> u.name.equals("exotic-mod-luminance"));
assertNotNull(type, "A mod unit must be loaded.");
assertTrue(type.weapons.size > 0, "A mod unit must have a weapon.");
Vars.world.loadMap(ApplicationTests.testMap);
Unit unit = type.spawn(0, 0);
//check for crash
unit.update();
assertTrue(unit.health > 0, "Unit must be spawned and alive.");
assertTrue(Groups.unit.size() > 0, "Unit must be spawned and alive.");
//just an extra sanity check
Log.info("Modded units: @", Vars.content.units().select(u -> u.minfo.mod != null));
}
}

View File

@ -0,0 +1,39 @@
import arc.util.*;
import mindustry.*;
import mindustry.gen.*;
import mindustry.type.*;
import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.*;
//grabs a version-locked Heavy Armaments Industries commit and makes sure it initializes correctly
//this mod was chosen because:
//- it is one of the top JS mods, based on stars
//- it contains both JS and JSON, which can be used to test compatibility of the two
//- it can be used server-side (unlike FactoryDustry, which is a client-side texture pack that cannot be tested here)
public class ModTestHAI extends GenericModTest{
@Test
public void begin(){
grabMod("https://github.com/Eschatologue/Heavy-Armaments-Industries/archive/d996e92dcf9a30a6acb7b3bfdfb6522dddc3804c.zip");
checkExistence("heavy-armaments");
UnitType type = Vars.content.units().find(u -> u.name.equals("heavy-armaments-t3A_copter"));
assertNotNull(type, "A mod unit must be loaded.");
assertTrue(type.weapons.size > 0, "A mod unit must have a weapon.");
Vars.world.loadMap(ApplicationTests.testMap);
Unit unit = type.spawn(0, 0);
//check for crash
unit.update();
assertTrue(unit.health > 0, "Unit must be spawned and alive.");
assertTrue(Groups.unit.size() > 0, "Unit must be spawned and alive.");
//just an extra sanity check
Log.info("Modded units: @", Vars.content.units().select(u -> u.minfo.mod != null));
}
}

View File

@ -1,105 +0,0 @@
import arc.struct.*;
import arc.util.*;
import mindustry.content.*;
import mindustry.core.*;
import mindustry.core.GameState.*;
import mindustry.game.*;
import mindustry.io.SaveIO.*;
import mindustry.type.*;
import mindustry.world.*;
import mindustry.world.blocks.storage.*;
import org.junit.jupiter.api.*;
import static mindustry.Vars.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.DynamicTest.dynamicTest;
public class SectorTests{
@BeforeAll
static void launchApplication(){
ApplicationTests.launchApplication();
}
@BeforeEach
void resetWorld(){
Time.setDeltaProvider(() -> 1f);
logic.reset();
state.set(State.menu);
}
@TestFactory
DynamicTest[] testZoneValidity(){
Seq<DynamicTest> out = new Seq<>();
if(world == null) world = new World();
for(SectorPreset zone : content.sectors()){
out.add(dynamicTest(zone.name, () -> {
logic.reset();
try{
world.loadGenerator(zone.generator.map.width, zone.generator.map.height, zone.generator::generate);
}catch(SaveException e){
//fails randomly and I don't care about fixing it
e.printStackTrace();
return;
}
zone.rules.get(state.rules);
ObjectSet<Item> resources = new ObjectSet<>();
boolean hasSpawnPoint = false;
for(Tile tile : world.tiles){
if(tile.drop() != null){
resources.add(tile.drop());
}
if(tile.block() instanceof CoreBlock && tile.team() == state.rules.defaultTeam){
hasSpawnPoint = true;
}
}
Seq<SpawnGroup> spawns = state.rules.spawns;
int bossWave = 0;
if(state.rules.winWave > 0){
bossWave = state.rules.winWave;
}else{
outer:
for(int i = 1; i <= 1000; i++){
for(SpawnGroup spawn : spawns){
if(spawn.effect == StatusEffects.boss && spawn.getSpawned(i) > 0){
bossWave = i;
break outer;
}
}
}
}
if(state.rules.attackMode){
bossWave = 100;
}else{
assertNotEquals(0, bossWave, "Sector doesn't have a boss wave.");
}
//TODO check for difficulty?
for(int i = 1; i <= bossWave; i++){
int total = 0;
for(SpawnGroup spawn : spawns){
total += spawn.getSpawned(i);
}
assertNotEquals(0, total, "Sector " + zone + " has no spawned enemies at wave " + i);
//TODO this is flawed and needs to be changed later
//assertTrue(total < 75, "Sector spawns too many enemies at wave " + i + " (" + total + ")");
}
assertEquals(1, Team.sharded.cores().size, "Sector must have one core: " + zone);
assertTrue(Team.sharded.core().items.total() < 1000, "Sector must not have starting resources: " + zone);
assertTrue(hasSpawnPoint, "Sector \"" + zone.name + "\" has no spawn points.");
assertTrue(spawner.countSpawns() > 0 || (state.rules.attackMode && state.rules.waveTeam.data().hasCore()), "Sector \"" + zone.name + "\" has no enemy spawn points: " + spawner.countSpawns());
}));
}
return out.toArray(DynamicTest.class);
}
}

View File

@ -1,9 +1,18 @@
package power;
import mindustry.content.*;
import mindustry.type.*;
import mindustry.world.*;
import mindustry.world.blocks.power.PowerGenerator.*;
import mindustry.world.blocks.power.*;
import mindustry.world.blocks.production.*;
import org.junit.jupiter.api.*;
import static org.junit.jupiter.api.Assertions.*;
/** Tests for direct power consumers. */
public class DirectConsumerTests extends PowerTestFixture{
//TODO reimplement
/*
@Test
void noPowerRequestedWithNoItems(){
testUnitFactory(0, 0, 0.08f, 0.08f, 1f);
@ -21,26 +30,26 @@ public class DirectConsumerTests extends PowerTestFixture{
}
void testUnitFactory(int siliconAmount, int leadAmount, float producedPower, float requestedPower, float expectedSatisfaction){
Tile consumerTile = createFakeTile(0, 0, new UnitFactory("fakefactory"){{
entityType = UnitFactoryEntity::new;
unitType = UnitTypes.spirit;
produceTime = 60;
Tile ct = createFakeTile(0, 0, new GenericCrafter("fakefactory"){{
hasPower = true;
hasItems = true;
consumes.power(requestedPower);
consumes.items(new ItemStack(Items.silicon, 30), new ItemStack(Items.lead, 30));
}});
consumerTile.entity.items.add(Items.silicon, siliconAmount);
consumerTile.entity.items.add(Items.lead, leadAmount);
ct.block().init();
ct.build.items.add(Items.silicon, siliconAmount);
ct.build.items.add(Items.lead, leadAmount);
Tile producerTile = createFakeTile(2, 0, createFakeProducerBlock(producedPower));
producerTile.<PowerGenerator.GeneratorEntity>ent().productionEfficiency = 1f;
((GeneratorBuild)producerTile.build).productionEfficiency = 1f;
PowerGraph graph = new PowerGraph();
graph.add(producerTile.entity);
graph.add(consumerTile.entity);
graph.add(producerTile.build);
graph.add(ct.build);
consumerTile.entity.update();
ct.build.update();
graph.update();
assertEquals(expectedSatisfaction, consumerTile.entity.power.status);
}*/
assertEquals(expectedSatisfaction, ct.build.power.status);
}
}

View File

@ -24,7 +24,6 @@ import static org.junit.jupiter.api.DynamicTest.dynamicTest;
* Any expected power amount (produced, consumed, buffered) should be affected by FakeThreadHandler.fakeDelta but status should not!
*/
public class ItemLiquidGeneratorTests extends PowerTestFixture{
private ItemLiquidGenerator generator;
private Tile tile;
private ItemLiquidGeneratorBuild entity;

View File

@ -176,7 +176,7 @@ public class Generators{
for(int x = 0; x < dim; x++){
for(int y = 0; y < dim; y++){
float dst = Mathf.dst((float)x/dim, (float)y/dim, 0.5f, 0.5f) * 2f;
if(dst < 1.2f && RidgedPerlin.noise2d(1, x, y, 3, 1f / 40f) - dst*(1f-fract) > 0.16f){
if(dst < 1.2f && Ridged.noise2d(1, x, y, 3, 1f / 40f) - dst*(1f-fract) > 0.16f){
image.setRaw(x, y, Color.whiteRgba);
}
}
@ -220,7 +220,7 @@ public class Generators{
TextureRegion[] regions = block.getGeneratedIcons();
if(block.variants > 0){
if(block.variants > 0 || block instanceof Floor){
for(TextureRegion region : block.variantRegions()){
GenRegion gen = (GenRegion)region;
if(gen.path == null) continue;
@ -488,7 +488,7 @@ public class Generators{
image.each((x, y) -> {
//add darker cracks on top
boolean rValue = Math.max(RidgedPerlin.noise2d(1, x, y, 3, 1f / (20f + image.width/8f)), 0) > 0.16f;
boolean rValue = Math.max(Ridged.noise2d(1, x, y, 3, 1f / (20f + image.width/8f)), 0) > 0.16f;
//cut out random chunks with voronoi
boolean vval = vn.noise(x, y, 1f / (14f + image.width/40f)) > 0.47;
@ -601,14 +601,11 @@ public class Generators{
/** Generates a scorch pixmap based on parameters. Thread safe, unless multiple scorch generators are running in parallel. */
public static class ScorchGenerator{
private static final Simplex sim = new Simplex();
public int size = 80, seed = 0, color = Color.whiteRgba;
public double scale = 18, pow = 2, octaves = 4, pers = 0.4, add = 2, nscl = 4.5f;
public Pixmap generate(){
Pixmap pix = new Pixmap(size, size);
sim.setSeed(seed);
pix.each((x, y) -> {
double dst = Mathf.dst(x, y, size/2, size/2) / (size / 2f);
@ -621,7 +618,7 @@ public class Generators{
}
private double noise(float angle){
return Math.pow(sim.octaveNoise2D(octaves, pers, 1 / scale, Angles.trnsx(angle, size/2f) + size/2f, Angles.trnsy(angle, size/2f) + size/2f), pow);
return Math.pow(Simplex.noise2d(seed, octaves, pers, 1 / scale, Angles.trnsx(angle, size/2f) + size/2f, Angles.trnsy(angle, size/2f) + size/2f), pow);
}
}