diff --git a/.gitignore b/.gitignore index b33484f175..00ff121460 100644 --- a/.gitignore +++ b/.gitignore @@ -28,6 +28,7 @@ logs/ /ios/src/io/anuke/mindustry/gen/ /core/src/io/anuke/mindustry/gen/ ios/robovm.properties +packr-out/ config/ *.gif diff --git a/.travis.yml b/.travis.yml index c0f4f1a5e8..8231bc68f7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,7 @@ jdk: - openjdk8 script: +- "git clone --depth=1 --branch=master https://github.com/Anuken/Arc ../Arc" - "./gradlew test" - "./gradlew desktop:dist -Pbuildversion=${TRAVIS_TAG:1}" - "./gradlew server:dist -Pbuildversion=${TRAVIS_TAG:1}" @@ -17,4 +18,4 @@ deploy: - "server/build/libs/server-release.jar" on: repo: Anuken/Mindustry - tags: true \ No newline at end of file + tags: true diff --git a/README.md b/README.md index f85d9cb702..85b5a0b5e8 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,10 @@ _Building:_ `./gradlew desktop:dist` Server builds are bundled with each released build (in Releases). If you'd rather compile on your own, replace 'desktop' with 'server', e.g. `gradlew server:dist`. +##### Troubleshooting + +If the terminal returns `Permission denied` or `Command not found` on Mac/Linux, run `chmod +x ./gradlew` before running `./gradlew`. *This is a one-time procedure.* + --- Gradle may take up to several minutes to download files. Be patient.
diff --git a/android/build.gradle b/android/build.gradle index 5e2fb3e7f6..f218d1876a 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -8,7 +8,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.3.1' + classpath 'com.android.tools.build:gradle:3.3.2' } } diff --git a/android/src/io/anuke/mindustry/AndroidLauncher.java b/android/src/io/anuke/mindustry/AndroidLauncher.java index 323352d9eb..a7bb47034b 100644 --- a/android/src/io/anuke/mindustry/AndroidLauncher.java +++ b/android/src/io/anuke/mindustry/AndroidLauncher.java @@ -100,7 +100,7 @@ public class AndroidLauncher extends AndroidApplication{ @Override public void beginForceLandscape(){ - setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); + setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE); } @Override @@ -178,12 +178,14 @@ public class AndroidLauncher extends AndroidApplication{ ui.showError("$save.import.invalid"); } }else if(map){ //open map + FileHandle file = Core.files.local("temp-map." + mapExtension); + file.write(inStream, false); Core.app.post(() -> { System.out.println("Opening map."); if(!ui.editor.isShown()){ ui.editor.show(); } - ui.editor.beginEditMap(inStream); + ui.editor.beginEditMap(file); }); } }); diff --git a/build.gradle b/build.gradle index d5c67790b1..74fb990a22 100644 --- a/build.gradle +++ b/build.gradle @@ -10,6 +10,7 @@ buildscript{ dependencies{ classpath 'com.mobidevelop.robovm:robovm-gradle-plugin:2.3.5' classpath "com.badlogicgames.gdx:gdx-tools:1.9.9" + classpath "com.badlogicgames.packr:packr:2.1-SNAPSHOT" } } diff --git a/core/assets-raw/fonts/cyrillic/Exo2-Regular.ttf b/core/assets-raw/fonts/Exo2-Regular.ttf similarity index 100% rename from core/assets-raw/fonts/cyrillic/Exo2-Regular.ttf rename to core/assets-raw/fonts/Exo2-Regular.ttf diff --git a/core/assets-raw/fonts/NanumBarunGothic.ttf b/core/assets-raw/fonts/NanumBarunGothic.ttf new file mode 100644 index 0000000000..658cd3c239 Binary files /dev/null and b/core/assets-raw/fonts/NanumBarunGothic.ttf differ diff --git a/core/assets-raw/fonts/OpenSansEmoji.ttf b/core/assets-raw/fonts/OpenSansEmoji.ttf new file mode 100644 index 0000000000..57d86a62bb Binary files /dev/null and b/core/assets-raw/fonts/OpenSansEmoji.ttf differ diff --git a/core/assets-raw/fonts/chinese/wqy-microhei.ttc b/core/assets-raw/fonts/chinese/wqy-microhei.ttc deleted file mode 100644 index 2c9bc2d4e0..0000000000 Binary files a/core/assets-raw/fonts/chinese/wqy-microhei.ttc and /dev/null differ diff --git a/core/assets-raw/fonts/font_latin.ttf b/core/assets-raw/fonts/font_latin.ttf new file mode 100644 index 0000000000..cebae09c33 Binary files /dev/null and b/core/assets-raw/fonts/font_latin.ttf differ diff --git a/core/assets-raw/fonts/korean/Sunflower-Medium.ttf b/core/assets-raw/fonts/korean/Sunflower-Medium.ttf deleted file mode 100644 index ad37058a5c..0000000000 Binary files a/core/assets-raw/fonts/korean/Sunflower-Medium.ttf and /dev/null differ diff --git a/core/assets-raw/fonts/pixel_UNEDITED.ttf b/core/assets-raw/fonts/pixel_UNEDITED.ttf deleted file mode 100644 index 3be17ee696..0000000000 Binary files a/core/assets-raw/fonts/pixel_UNEDITED.ttf and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/distribution/mass-driver-turret.png b/core/assets-raw/sprites/blocks/distribution/mass-driver.png similarity index 100% rename from core/assets-raw/sprites/blocks/distribution/mass-driver-turret.png rename to core/assets-raw/sprites/blocks/distribution/mass-driver.png diff --git a/core/assets-raw/sprites/blocks/environment/moss1.png b/core/assets-raw/sprites/blocks/environment/moss1.png new file mode 100644 index 0000000000..8344698387 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/moss1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/moss2.png b/core/assets-raw/sprites/blocks/environment/moss2.png new file mode 100644 index 0000000000..ed1a8981fb Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/moss2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/moss3.png b/core/assets-raw/sprites/blocks/environment/moss3.png new file mode 100644 index 0000000000..ea5072a8dd Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/moss3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/pack.json b/core/assets-raw/sprites/blocks/environment/pack.json new file mode 100644 index 0000000000..91480ffa76 --- /dev/null +++ b/core/assets-raw/sprites/blocks/environment/pack.json @@ -0,0 +1,8 @@ +{ + duplicatePadding: true, + combineSubdirectories: true, + flattenPaths: true, + maxWidth: 2048, + maxHeight: 2048, + fast: true, +} diff --git a/core/assets-raw/sprites/blocks/environment/pine.png b/core/assets-raw/sprites/blocks/environment/pine.png index 3e6f3c7ef8..13eee73aaa 100644 Binary files a/core/assets-raw/sprites/blocks/environment/pine.png and b/core/assets-raw/sprites/blocks/environment/pine.png differ diff --git a/core/assets-raw/sprites/blocks/environment/sand1.png b/core/assets-raw/sprites/blocks/environment/sand1.png index f6259baf64..73e2c6d635 100644 Binary files a/core/assets-raw/sprites/blocks/environment/sand1.png and b/core/assets-raw/sprites/blocks/environment/sand1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/sand2.png b/core/assets-raw/sprites/blocks/environment/sand2.png index ce03f296ba..4429bb584b 100644 Binary files a/core/assets-raw/sprites/blocks/environment/sand2.png and b/core/assets-raw/sprites/blocks/environment/sand2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/sand3.png b/core/assets-raw/sprites/blocks/environment/sand3.png index 7ff6f2e9f0..c358be019b 100644 Binary files a/core/assets-raw/sprites/blocks/environment/sand3.png and b/core/assets-raw/sprites/blocks/environment/sand3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/sandrocks-large.png b/core/assets-raw/sprites/blocks/environment/sandrocks-large.png new file mode 100644 index 0000000000..d91729fb22 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/sandrocks-large.png differ diff --git a/core/assets-raw/sprites/blocks/environment/sandrocks1.png b/core/assets-raw/sprites/blocks/environment/sandrocks1.png new file mode 100644 index 0000000000..5df0ef7fe1 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/sandrocks1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/sandrocks2.png b/core/assets-raw/sprites/blocks/environment/sandrocks2.png new file mode 100644 index 0000000000..70a4cea724 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/sandrocks2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-boulder1.png b/core/assets-raw/sprites/blocks/environment/shale-boulder1.png similarity index 100% rename from core/assets-raw/sprites/blocks/environment/stained-boulder1.png rename to core/assets-raw/sprites/blocks/environment/shale-boulder1.png diff --git a/core/assets-raw/sprites/blocks/environment/stained-boulder2.png b/core/assets-raw/sprites/blocks/environment/shale-boulder2.png similarity index 100% rename from core/assets-raw/sprites/blocks/environment/stained-boulder2.png rename to core/assets-raw/sprites/blocks/environment/shale-boulder2.png diff --git a/core/assets-raw/sprites/blocks/environment/shale1.png b/core/assets-raw/sprites/blocks/environment/shale1.png new file mode 100644 index 0000000000..5b44a22c0b Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/shale1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/shale2.png b/core/assets-raw/sprites/blocks/environment/shale2.png new file mode 100644 index 0000000000..bd6746d7a7 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/shale2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/shale3.png b/core/assets-raw/sprites/blocks/environment/shale3.png new file mode 100644 index 0000000000..f8678bd05f Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/shale3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-rocks-large.png b/core/assets-raw/sprites/blocks/environment/shalerocks-large.png similarity index 100% rename from core/assets-raw/sprites/blocks/environment/stained-rocks-large.png rename to core/assets-raw/sprites/blocks/environment/shalerocks-large.png diff --git a/core/assets-raw/sprites/blocks/environment/stainedrocks1.png b/core/assets-raw/sprites/blocks/environment/shalerocks1.png similarity index 100% rename from core/assets-raw/sprites/blocks/environment/stainedrocks1.png rename to core/assets-raw/sprites/blocks/environment/shalerocks1.png diff --git a/core/assets-raw/sprites/blocks/environment/stainedrocks2.png b/core/assets-raw/sprites/blocks/environment/shalerocks2.png similarity index 100% rename from core/assets-raw/sprites/blocks/environment/stainedrocks2.png rename to core/assets-raw/sprites/blocks/environment/shalerocks2.png diff --git a/core/assets-raw/sprites/blocks/environment/spore-moss1.png b/core/assets-raw/sprites/blocks/environment/spore-moss1.png new file mode 100644 index 0000000000..270349168a Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/spore-moss1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/spore-moss2.png b/core/assets-raw/sprites/blocks/environment/spore-moss2.png new file mode 100644 index 0000000000..0546666a22 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/spore-moss2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/spore-moss3.png b/core/assets-raw/sprites/blocks/environment/spore-moss3.png new file mode 100644 index 0000000000..4cfbe3ed3c Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/spore-moss3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-rocks-red-large.png b/core/assets-raw/sprites/blocks/environment/stained-rocks-red-large.png deleted file mode 100644 index 1697abb808..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/stained-rocks-red-large.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-rocks-red1.png b/core/assets-raw/sprites/blocks/environment/stained-rocks-red1.png deleted file mode 100644 index e646fcbba3..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/stained-rocks-red1.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-rocks-red2.png b/core/assets-raw/sprites/blocks/environment/stained-rocks-red2.png deleted file mode 100644 index f85c1882bc..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/stained-rocks-red2.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-rocks-yellow-large.png b/core/assets-raw/sprites/blocks/environment/stained-rocks-yellow-large.png deleted file mode 100644 index 055bd4cc44..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/stained-rocks-yellow-large.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-rocks-yellow1.png b/core/assets-raw/sprites/blocks/environment/stained-rocks-yellow1.png deleted file mode 100644 index 9e59a807c8..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/stained-rocks-yellow1.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-rocks-yellow2.png b/core/assets-raw/sprites/blocks/environment/stained-rocks-yellow2.png deleted file mode 100644 index 4788cb582a..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/stained-rocks-yellow2.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-rocks1.png b/core/assets-raw/sprites/blocks/environment/stained-rocks1.png deleted file mode 100644 index e0aa379812..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/stained-rocks1.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-rocks2.png b/core/assets-raw/sprites/blocks/environment/stained-rocks2.png deleted file mode 100644 index 7b6eabb5d1..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/stained-rocks2.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-stone-red1.png b/core/assets-raw/sprites/blocks/environment/stained-stone-red1.png deleted file mode 100644 index a32936fdb2..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/stained-stone-red1.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-stone-red2.png b/core/assets-raw/sprites/blocks/environment/stained-stone-red2.png deleted file mode 100644 index baae667241..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/stained-stone-red2.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-stone-red3.png b/core/assets-raw/sprites/blocks/environment/stained-stone-red3.png deleted file mode 100644 index 7269b8fd14..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/stained-stone-red3.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-stone-yellow1.png b/core/assets-raw/sprites/blocks/environment/stained-stone-yellow1.png deleted file mode 100644 index c2a6b18117..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/stained-stone-yellow1.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-stone-yellow2.png b/core/assets-raw/sprites/blocks/environment/stained-stone-yellow2.png deleted file mode 100644 index 20b285b768..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/stained-stone-yellow2.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-stone-yellow3.png b/core/assets-raw/sprites/blocks/environment/stained-stone-yellow3.png deleted file mode 100644 index 2a92d862be..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/stained-stone-yellow3.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-stone1.png b/core/assets-raw/sprites/blocks/environment/stained-stone1.png deleted file mode 100644 index 464ac94806..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/stained-stone1.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-stone2.png b/core/assets-raw/sprites/blocks/environment/stained-stone2.png deleted file mode 100644 index 36a8896dd8..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/stained-stone2.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/stained-stone3.png b/core/assets-raw/sprites/blocks/environment/stained-stone3.png deleted file mode 100644 index 092ec5dac7..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/stained-stone3.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/stainedrocks-large.png b/core/assets-raw/sprites/blocks/environment/stainedrocks-large.png deleted file mode 100644 index 46c60a3be4..0000000000 Binary files a/core/assets-raw/sprites/blocks/environment/stainedrocks-large.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/differential-generator-top.png b/core/assets-raw/sprites/blocks/power/differential-generator-top.png similarity index 100% rename from core/assets-raw/sprites/blocks/environment/differential-generator-top.png rename to core/assets-raw/sprites/blocks/power/differential-generator-top.png diff --git a/core/assets-raw/sprites/blocks/environment/differential-generator.png b/core/assets-raw/sprites/blocks/power/differential-generator.png similarity index 100% rename from core/assets-raw/sprites/blocks/environment/differential-generator.png rename to core/assets-raw/sprites/blocks/power/differential-generator.png diff --git a/core/assets-raw/sprites/blocks/turrets/hail.png b/core/assets-raw/sprites/blocks/turrets/hail.png index f54b439dbc..e679043a66 100644 Binary files a/core/assets-raw/sprites/blocks/turrets/hail.png and b/core/assets-raw/sprites/blocks/turrets/hail.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/scatter.png b/core/assets-raw/sprites/blocks/turrets/scatter.png new file mode 100644 index 0000000000..f6e1d7ff61 Binary files /dev/null and b/core/assets-raw/sprites/blocks/turrets/scatter.png differ diff --git a/core/assets-raw/sprites/blocks/units/crawler-factory-top-open.png b/core/assets-raw/sprites/blocks/units/crawler-factory-top-open.png new file mode 100644 index 0000000000..290db9d373 Binary files /dev/null and b/core/assets-raw/sprites/blocks/units/crawler-factory-top-open.png differ diff --git a/core/assets-raw/sprites/blocks/units/crawler-factory-top.png b/core/assets-raw/sprites/blocks/units/crawler-factory-top.png new file mode 100644 index 0000000000..f7cad4dbf6 Binary files /dev/null and b/core/assets-raw/sprites/blocks/units/crawler-factory-top.png differ diff --git a/core/assets-raw/sprites/blocks/units/crawler-factory.png b/core/assets-raw/sprites/blocks/units/crawler-factory.png new file mode 100644 index 0000000000..144156ae68 Binary files /dev/null and b/core/assets-raw/sprites/blocks/units/crawler-factory.png differ diff --git a/core/assets-raw/sprites/ui/check-off.png b/core/assets-raw/sprites/ui/check-off.png index b5f0e770c1..4ab1f7fae8 100644 Binary files a/core/assets-raw/sprites/ui/check-off.png and b/core/assets-raw/sprites/ui/check-off.png differ diff --git a/core/assets-raw/sprites/ui/check-on-over.png b/core/assets-raw/sprites/ui/check-on-over.png index 0f4c0ae981..80f373a89f 100644 Binary files a/core/assets-raw/sprites/ui/check-on-over.png and b/core/assets-raw/sprites/ui/check-on-over.png differ diff --git a/core/assets-raw/sprites/ui/check-on.png b/core/assets-raw/sprites/ui/check-on.png index 3d7637aa8d..57cc8a7484 100644 Binary files a/core/assets-raw/sprites/ui/check-on.png and b/core/assets-raw/sprites/ui/check-on.png differ diff --git a/core/assets-raw/sprites/ui/check-over.png b/core/assets-raw/sprites/ui/check-over.png index 747acd3e0c..2501a9daa9 100644 Binary files a/core/assets-raw/sprites/ui/check-over.png and b/core/assets-raw/sprites/ui/check-over.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-add.png b/core/assets-raw/sprites/ui/icons/icon-add.png index 2cee82e07d..50c7a2c330 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-add.png and b/core/assets-raw/sprites/ui/icons/icon-add.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-file-image.png b/core/assets-raw/sprites/ui/icons/icon-file-image.png index 254ea95f3d..5b0d2adbe5 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-file-image.png and b/core/assets-raw/sprites/ui/icons/icon-file-image.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-fill.png b/core/assets-raw/sprites/ui/icons/icon-fill.png index 79bc8b2c39..25d439a830 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-fill.png and b/core/assets-raw/sprites/ui/icons/icon-fill.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/edge-stencil-smooth.png b/core/assets-raw/sprites_replacement/blocks/environment/edge-stencil-smooth.png index 65a450a798..55f4b9fb03 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/environment/edge-stencil-smooth.png and b/core/assets-raw/sprites_replacement/blocks/environment/edge-stencil-smooth.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/metal-floor-2.png b/core/assets-raw/sprites_replacement/blocks/environment/metal-floor-2.png new file mode 100644 index 0000000000..563338725b Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/metal-floor-2.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/metal-floor-5.png b/core/assets-raw/sprites_replacement/blocks/environment/metal-floor-5.png new file mode 100644 index 0000000000..ed2bc67e17 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/metal-floor-5.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/metal-floor-damaged5.png b/core/assets-raw/sprites_replacement/blocks/environment/metal-floor-damaged5.png new file mode 100644 index 0000000000..5d36f9193e Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/metal-floor-damaged5.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/metal-floor.png b/core/assets-raw/sprites_replacement/blocks/environment/metal-floor.png new file mode 100644 index 0000000000..d0085b65d9 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/metal-floor.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/pine.png b/core/assets-raw/sprites_replacement/blocks/environment/pine.png new file mode 100644 index 0000000000..fcdc3e71fc Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/pine.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/salt.png b/core/assets-raw/sprites_replacement/blocks/environment/salt.png new file mode 100644 index 0000000000..df9fd72915 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/salt.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/sand-water.png b/core/assets-raw/sprites_replacement/blocks/environment/sand-water.png index 0144066175..4ac2222ed3 100644 Binary files a/core/assets-raw/sprites_replacement/blocks/environment/sand-water.png and b/core/assets-raw/sprites_replacement/blocks/environment/sand-water.png differ diff --git a/core/assets-raw/sprites_replacement/blocks/environment/spore-pine.png b/core/assets-raw/sprites_replacement/blocks/environment/spore-pine.png new file mode 100644 index 0000000000..661c4caeb7 Binary files /dev/null and b/core/assets-raw/sprites_replacement/blocks/environment/spore-pine.png differ diff --git a/core/assets-raw/sprites_replacement/editor/block-border-editor.png b/core/assets-raw/sprites_replacement/editor/block-border-editor.png new file mode 100644 index 0000000000..415c5a6849 Binary files /dev/null and b/core/assets-raw/sprites_replacement/editor/block-border-editor.png differ diff --git a/core/assets-raw/sprites_replacement/editor/clear-editor.png b/core/assets-raw/sprites_replacement/editor/clear-editor.png new file mode 100644 index 0000000000..a804d435b6 Binary files /dev/null and b/core/assets-raw/sprites_replacement/editor/clear-editor.png differ diff --git a/core/assets-raw/sprites_replacement/editor/pack.json b/core/assets-raw/sprites_replacement/editor/pack.json new file mode 100644 index 0000000000..91480ffa76 --- /dev/null +++ b/core/assets-raw/sprites_replacement/editor/pack.json @@ -0,0 +1,8 @@ +{ + duplicatePadding: true, + combineSubdirectories: true, + flattenPaths: true, + maxWidth: 2048, + maxHeight: 2048, + fast: true, +} diff --git a/core/assets-raw/sprites_replacement/items/item-sand.png b/core/assets-raw/sprites_replacement/items/item-sand.png index 1c78141fda..ec9c497fd3 100644 Binary files a/core/assets-raw/sprites_replacement/items/item-sand.png and b/core/assets-raw/sprites_replacement/items/item-sand.png differ diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 8032ddd07a..4f32062daa 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -194,11 +194,26 @@ editor.oregen.info = Ore Generation: editor.mapinfo = Map Info editor.author = Author: editor.description = Description: +editor.waves = Waves: +waves.title = Waves +waves.remove = Remove +waves.never = +waves.every = every +waves.waves = wave(s) +waves.perspawn = per spawn +waves.to = to +waves.boss = Boss +editor.default = [LIGHT_GRAY] +edit = Edit... editor.name = Name: editor.teams = Teams editor.elevation = Elevation -editor.errorimageload = Error loading file:\n[accent]{0} -editor.errorimagesave = Error saving file:\n[accent]{0} +editor.errorload = Error loading file:\n[accent]{0} +editor.errorsave = Error saving file:\n[accent]{0} +editor.errorname = Map has no name defined. +editor.update = Update +editor.randomize = Randomize +editor.apply = Apply editor.generate = Generate editor.resize = Resize editor.loadmap = Load Map @@ -227,6 +242,22 @@ editor.mapname = Map Name: editor.overwrite = [accent]Warning!\nThis overwrites an existing map. editor.overwrite.confirm = [scarlet]Warning![] A map with this name already exists. Are you sure you want to overwrite it? editor.selectmap = Select a map to load: +filters.empty = [LIGHT_GRAY]No filters! Add one with the button below. +filter.distort = Distort +filter.noise = Noise +filter.ore = Ore +filter.rivernoise = River Noise +filter.scatter = Scatter +filter.terrain = Terrain +filter.option.scale = Scale +filter.option.mag = Magnitude +filter.option.threshold = Threshold +filter.option.circle-scale = Circle Scale +filter.option.octaves = Octaves +filter.option.falloff = Falloff +filter.option.floor = Floor +filter.option.wall = Wall +filter.option.ore = Ore width = Width: height = Height: menu = Menu @@ -278,14 +309,9 @@ zone.groundZero.name = Ground Zero zone.craters.name = The Craters zone.frozenForest.name = Frozen Forest zone.ruinousShores.name = Ruinous Shores -zone.crags.name = Crags zone.stainedMountains.name = Stained Mountains -zone.impact0079.name = Impact 0079 zone.desolateRift.name = Desolate Rift -zone.arcticDesert.name = Arctic Desert -zone.dryWastes.name = Dry Wastes zone.nuclearComplex.name = Nuclear Production Complex -zone.moltenFault.name = Molten Fault settings.language = Language settings.reset = Reset to Defaults @@ -305,7 +331,8 @@ no = No info.title = Info error.title = [crimson]An error has occured error.crashtitle = An error has occured -blocks.outputspeed = Drill Speed: {0}/s +blocks.outputspeed = Drill Speed: {0}/ +blocks.efficiency = Efficiency: {0}% blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = Block Info blocks.powerbalance = Power: {0} @@ -313,6 +340,7 @@ blocks.poweroutput = Power Output: {0} blocks.powercapacity = Power Capacity blocks.powershot = Power/Shot blocks.targetsair = Targets Air +blocks.items = Items: {0} blocks.itemsmoved = Move Speed blocks.shootrange = Range blocks.size = Size @@ -372,10 +400,11 @@ category.general = General category.power = Power category.liquids = Liquids category.items = Items -category.crafting = Crafting +category.crafting = Input/Output category.shooting = Shooting category.optional = Optional Enhancements -setting.indicators.name = Ally Indicators +setting.animatedwater.name = Animated Water +setting.indicators.name = Enemy/Ally Indicators setting.autotarget.name = Auto-Target setting.fpscap.name = Max FPS setting.fpscap.none = None @@ -488,8 +517,8 @@ liquid.oil.name = Oil liquid.cryofluid.name = Cryofluid mech.alpha-mech.name = Alpha mech.alpha-mech.weapon = Heavy Repeater -mech.alpha-mech.ability = Drone Swarm -mech.alpha-mech.description = The standard mech. Has decent speed and damage output; can create up to 3 drones for increased offensive capability. +mech.alpha-mech.ability = None +mech.alpha-mech.description = The standard mech. Has decent speed and damage output. mech.delta-mech.name = Delta mech.delta-mech.weapon = Arc Generator mech.delta-mech.ability = Discharge @@ -529,6 +558,16 @@ mech.ability = [LIGHT_GRAY]Ability: {0} liquid.heatcapacity = [LIGHT_GRAY]Heat Capacity: {0} liquid.viscosity = [LIGHT_GRAY]Viscosity: {0} liquid.temperature = [LIGHT_GRAY]Temperature: {0} + +block.grass.name = Grass +block.salt.name = Salt +block.sandrocks.name = Sand Rocks +block.spore-pine.name = Spore Pine +block.shale.name = Shale +block.shale-boulder.name = Shale Boulder +block.moss.name = Moss +block.spore-moss.name = Spore Moss +block.shalerocks.name = Shale Rocks block.scrap-wall.name = Scrap Wall block.scrap-wall-large.name = Large Scrap Wall block.scrap-wall-huge.name = Huge Scrap Wall @@ -563,13 +602,6 @@ block.pine.name = Pine block.white-tree-dead.name = White Tree Dead block.white-tree.name = White Tree block.spore-cluster.name = Spore Cluster -block.stained-rocks.name = Stained Rocks -block.stained-stone.name = Stained Stone -block.stained-rocks-red.name = Stained Rocks Red -block.stained-stone-red.name = Stained Stone Red -block.stained-rocks-yellow.name = Stained Rocks Yellow -block.stained-stone-yellow.name = Stained Stone Yellow -block.stained-boulder.name = Stained Boulder block.metal-floor.name = Metal Floor block.metal-floor-2.name = Metal Floor 2 block.metal-floor-3.name = Metal Floor 3 @@ -590,6 +622,7 @@ block.thorium-wall-large.name = Large Thorium Wall block.door.name = Door block.door-large.name = Large Door block.duo.name = Duo +block.scatter.name = Scatter block.hail.name = Hail block.lancer.name = Lancer block.conveyor.name = Conveyor @@ -656,6 +689,7 @@ block.phantom-factory.name = Phantom Drone Factory block.wraith-factory.name = Wraith Fighter Factory block.ghoul-factory.name = Ghoul Bomber Factory block.dagger-factory.name = Dagger Mech Factory +block.crawler-factory.name = Crawler Mech Factory block.titan-factory.name = Titan Mech Factory block.fortress-factory.name = Fortress Mech Factory block.revenant-factory.name = Revenant Fighter Factory @@ -750,8 +784,9 @@ block.mend-projector.description = Periodically heals blocks in its vicinity. block.overdrive-projector.description = Increases the speed of nearby buildings like drills and conveyors. block.force-projector.description = Creates a hexagonal force field around itself, protecting buildings and units inside from damage through bullets. block.shock-mine.description = Damages enemies stepping on the mine. Nearly invisible to the enemy. -block.duo.description = A small, cheap turret. -block.arc.description = A small turret which shoots electricity in a random arc towards the enemy. +block.duo.description = A small, cheap turret. Useful against ground units. +block.scatter.description = A medium-sized anti-air turret. Sprays clumps of lead or scrap flak at enemy units. +block.arc.description = A small close-range turret which shoots electricity in a random arc towards the enemy. block.hail.description = A small artillery turret. block.lancer.description = A medium-sized turret which shoots charged electricity beams. block.wave.description = A medium-sized rapid-fire turret which shoots liquid bubbles. @@ -812,6 +847,7 @@ block.wraith-factory.description = Produces fast, hit-and-run interceptor units. block.ghoul-factory.description = Produces heavy carpet bombers. block.dagger-factory.description = Produces basic ground units. block.titan-factory.description = Produces advanced, armored ground units. + block.fortress-factory.description = Produces heavy artillery ground units. block.revenant-factory.description = Produces heavy laser air units. block.repair-point.description = Continuously heals the closest damaged unit in its vicinity. @@ -835,4 +871,4 @@ block.power-source.description = Infinitely outputs power. Sandbox only. block.power-void.description = Voids all power inputted into it. Sandbox only. liquid.water.description = Commonly used for cooling machines and waste processing. liquid.oil.description = Can be burnt, exploded or used as a coolant. -liquid.cryofluid.description = The most efficient liquid for cooling things down. +liquid.cryofluid.description = The most efficient liquid for cooling things down. \ No newline at end of file diff --git a/core/assets/bundles/bundle_cs.properties b/core/assets/bundles/bundle_cs.properties index 9c665955be..dd60dac4c7 100644 --- a/core/assets/bundles/bundle_cs.properties +++ b/core/assets/bundles/bundle_cs.properties @@ -192,11 +192,26 @@ editor.oregen.info = Generování nerostných zdrojů: editor.mapinfo = Informace o mapě editor.author = Autor: editor.description = Popis: +editor.waves = Waves: +waves.title = Waves +waves.remove = Remove +waves.never = +waves.every = every +waves.waves = wave(s) +waves.perspawn = per spawn +waves.to = to +waves.boss = Boss +editor.default = [LIGHT_GRAY] +edit = Edit... editor.name = Jméno: editor.teams = Týmy editor.elevation = Výška -editor.errorimageload = Chyba při načítání souboru:\n[accent]{0} -editor.errorimagesave = Chyba při ukládání souboru:\n[accent]{0} +editor.errorload = Error loading file:\n[accent]{0} +editor.errorsave = Error saving file:\n[accent]{0} +editor.errorname = Map has no name defined. +editor.update = Update +editor.randomize = Randomize +editor.apply = Apply editor.generate = Generovat editor.resize = Změnit velikost editor.loadmap = Načíst mapu @@ -225,6 +240,21 @@ editor.mapname = Jméno mapy: editor.overwrite = [accent]Varování!\nToto přepíše již existující mapu. editor.overwrite.confirm = [scarlet]Varování![] Mapa s tímto jménem již existuje. Jsi si jistý že ji chceš přepsat? editor.selectmap = Vyber mapu k načtení: +filter.distort = Distort +filter.noise = Noise +filter.ore = Ore +filter.rivernoise = River Noise +filter.scatter = Scatter +filter.terrain = Terrain +filter.option.scale = Scale +filter.option.mag = Magnitude +filter.option.threshold = Threshold +filter.option.circle-scale = Circle Scale +filter.option.octaves = Octaves +filter.option.falloff = Falloff +filter.option.floor = Floor +filter.option.wall = Wall +filter.option.ore = Ore width = Šířka: height = Výška: menu = Hlavní menu @@ -273,14 +303,9 @@ zone.groundZero.name = Ground Zero zone.craters.name = The Craters zone.frozenForest.name = Frozen Forest zone.ruinousShores.name = Ruinous Shores -zone.crags.name = Crags zone.stainedMountains.name = Stained Mountains -zone.impact0079.name = Impact 0079 zone.desolateRift.name = Desolate Rift -zone.arcticDesert.name = Arctic Desert -zone.dryWastes.name = Dry Wastes zone.nuclearComplex.name = Nuclear Production Complex -zone.moltenFault.name = Molten Fault settings.language = Jazyk settings.reset = nastavit výchozí settings.rebind = Přenastavit @@ -300,6 +325,7 @@ info.title = Informace error.title = [crimson]Objevila se chyba error.crashtitle = Objevila se chyba blocks.outputspeed = Drill Speed: {0}/s +blocks.efficiency = Efficiency: {0}% blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = Informace o bloku blocks.powerbalance = Power: {0} @@ -307,6 +333,7 @@ blocks.poweroutput = Power Output: {0} blocks.powercapacity = Kapacita energie blocks.powershot = Energie na výstřel blocks.targetsair = Zaměřuje vzdušné jednotky +blocks.items = Items: {0} blocks.itemsmoved = Move Speed blocks.shootrange = Dostřel blocks.size = velikost @@ -369,6 +396,7 @@ category.items = Předměty category.crafting = Vyžaduje category.shooting = Střílí category.optional = Volitelné vylepšení +setting.animatedwater.name = Animated Water setting.indicators.name = Indikátor pro spojence setting.autotarget.name = Automaticky zaměřuje setting.fpscap.name = Max FPS @@ -523,6 +551,15 @@ mech.ability = [LIGHT_GRAY]Schopnost: {0} liquid.heatcapacity = [LIGHT_GRAY]Kapacita teploty: {0} liquid.viscosity = [LIGHT_GRAY]Viskozita: {0} liquid.temperature = [LIGHT_GRAY]Teplota: {0} +block.grass.name = Grass +block.salt.name = Salt +block.sandrocks.name = Sand Rocks +block.spore-pine.name = Spore Pine +block.shale.name = Shale +block.shale-boulder.name = Shale Boulder +block.moss.name = Moss +block.spore-moss.name = Spore Moss +block.shalerocks.name = Shale Rocks block.scrap-wall.name = Scrap Wall block.scrap-wall-large.name = Large Scrap Wall block.scrap-wall-huge.name = Huge Scrap Wall @@ -557,13 +594,6 @@ block.pine.name = Pine block.white-tree-dead.name = White Tree Dead block.white-tree.name = White Tree block.spore-cluster.name = Spore Cluster -block.stained-rocks.name = Stained Rocks -block.stained-stone.name = Stained Stone -block.stained-rocks-red.name = Stained Rocks Red -block.stained-stone-red.name = Stained Stone Red -block.stained-rocks-yellow.name = Stained Rocks Yellow -block.stained-stone-yellow.name = Stained Stone Yellow -block.stained-boulder.name = Stained Boulde block.metal-floor.name = Metal Floor block.metal-floor-2.name = Metal Floor 2 block.metal-floor-3.name = Metal Floor 3 @@ -584,6 +614,7 @@ block.thorium-wall-large.name = Velká thoriová stěna block.door.name = Dveře block.door-large.name = Velké dveře block.duo.name = Duo +block.scatter.name = Scatter block.hail.name = Hail block.lancer.name = Lancer block.conveyor.name = Dopravník @@ -650,6 +681,7 @@ block.phantom-factory.name = Továrna na Fantom Drony block.wraith-factory.name = Továrna na Wraithy block.ghoul-factory.name = Továrna na Ghůl Bombardéry block.dagger-factory.name = Továrna na Dagger Mechy +block.crawler-factory.name = Crawler Mech Factory block.titan-factory.name = Továrna na Titán Mechy block.fortress-factory.name = Továrna na Fortress Mechy block.revenant-factory.name = Továrna na Revenanty @@ -745,6 +777,7 @@ block.overdrive-projector.description = Zrychluje funkce blízkých struktůr ja block.force-projector.description = Vytvoří okolo sebe šestihrané silové pole, chrání jednotky a budovy uvnitř sebe vůči střelám. block.shock-mine.description = Působí poškození nepřátelským jednotkám při sešlápnutí. Skoro neviditelné nepřáteli. block.duo.description = Malá, levná střílna. +block.scatter.description = A medium-sized anti-air turret. Sprays clumps of lead or scrap flak at enemy units. block.arc.description = Malá střílna, která střílí elektřinu v náhodném oblouku po nepřátelských jednotkách. block.hail.description = Malá artilérní střílna. block.lancer.description = Středně velká střílna, která střílí nabité elektrické paprsky. diff --git a/core/assets/bundles/bundle_de.properties b/core/assets/bundles/bundle_de.properties index 2c9e710f68..3d08a494ec 100644 --- a/core/assets/bundles/bundle_de.properties +++ b/core/assets/bundles/bundle_de.properties @@ -192,11 +192,26 @@ editor.oregen.info = Erze generiert: editor.mapinfo = Karten Info editor.author = Author: editor.description = Beschreibung: +editor.waves = Waves: +waves.title = Waves +waves.remove = Remove +waves.never = +waves.every = every +waves.waves = wave(s) +waves.perspawn = per spawn +waves.to = to +waves.boss = Boss +editor.default = [LIGHT_GRAY] +edit = Edit... editor.name = Name: editor.teams = Teams editor.elevation = Höhe -editor.errorimageload = Fehler beim Laden des Bildes: [accent] {0} -editor.errorimagesave = Fehler beim Speichern des Bildes: [accent] {0} +editor.errorload = Error loading file:\n[accent]{0} +editor.errorsave = Error saving file:\n[accent]{0} +editor.errorname = Map has no name defined. +editor.update = Update +editor.randomize = Randomize +editor.apply = Apply editor.generate = Generieren editor.resize = Grösse\nanpassen editor.loadmap = Karte\nladen @@ -225,6 +240,21 @@ editor.mapname = Karten Name editor.overwrite = [accent] Warnung! Dies überschreibt eine vorhandene Karte. editor.overwrite.confirm = [scarlet]Warnung![] Eine Karte mit diesem Namen existiert bereits. Bist du sicher, dass du sie überschreiben willst? editor.selectmap = Wähle eine Karte zum Laden: +filter.distort = Distort +filter.noise = Noise +filter.ore = Ore +filter.rivernoise = River Noise +filter.scatter = Scatter +filter.terrain = Terrain +filter.option.scale = Scale +filter.option.mag = Magnitude +filter.option.threshold = Threshold +filter.option.circle-scale = Circle Scale +filter.option.octaves = Octaves +filter.option.falloff = Falloff +filter.option.floor = Floor +filter.option.wall = Wall +filter.option.ore = Ore width = Breite: height = Höhe: menu = Menü @@ -273,14 +303,9 @@ zone.groundZero.name = Ground Zero zone.craters.name = The Craters zone.frozenForest.name = Frozen Forest zone.ruinousShores.name = Ruinous Shores -zone.crags.name = Crags zone.stainedMountains.name = Stained Mountains -zone.impact0079.name = Impact 0079 zone.desolateRift.name = Desolate Rift -zone.arcticDesert.name = Arctic Desert -zone.dryWastes.name = Dry Wastes zone.nuclearComplex.name = Nuclear Production Complex -zone.moltenFault.name = Molten Fault settings.language = Sprache settings.reset = Auf Standard zurücksetzen settings.rebind = Zuweisen @@ -300,6 +325,7 @@ info.title = [accent]Info error.title = [crimson] Ein Fehler ist aufgetreten error.crashtitle = Ein Fehler ist aufgetreten! blocks.outputspeed = Drill Speed: {0}/s +blocks.efficiency = Efficiency: {0}% blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = Blockinfo: blocks.powerbalance = Power: {0} @@ -307,6 +333,7 @@ blocks.poweroutput = Power Output: {0} blocks.powercapacity = Kapazität blocks.powershot = Stromverbrauch/Schuss blocks.targetsair = Visiert Luft Einheiten an +blocks.items = Items: {0} blocks.itemsmoved = Move Speed blocks.shootrange = Reichweite blocks.size = Größe @@ -369,6 +396,7 @@ category.items = Materialien category.crafting = Erzeugung category.shooting = Schießen category.optional = Optional Enhancements +setting.animatedwater.name = Animated Water setting.indicators.name = Ally Indicators setting.autotarget.name = Auto-Zielauswahl setting.fpscap.name = Max FPS @@ -523,6 +551,15 @@ mech.ability = [LIGHT_GRAY]Fähigkeit: {0} liquid.heatcapacity = [LIGHT_GRAY]Wärmekapazität: {0} liquid.viscosity = [LIGHT_GRAY]Viskosität: {0} liquid.temperature = [LIGHT_GRAY]Temperatur: {0} +block.grass.name = Grass +block.salt.name = Salt +block.sandrocks.name = Sand Rocks +block.spore-pine.name = Spore Pine +block.shale.name = Shale +block.shale-boulder.name = Shale Boulder +block.moss.name = Moss +block.spore-moss.name = Spore Moss +block.shalerocks.name = Shale Rocks block.scrap-wall.name = Scrap Wall block.scrap-wall-large.name = Large Scrap Wall block.scrap-wall-huge.name = Huge Scrap Wall @@ -557,13 +594,6 @@ block.pine.name = Pine block.white-tree-dead.name = White Tree Dead block.white-tree.name = White Tree block.spore-cluster.name = Spore Cluster -block.stained-rocks.name = Stained Rocks -block.stained-stone.name = Stained Stone -block.stained-rocks-red.name = Stained Rocks Red -block.stained-stone-red.name = Stained Stone Red -block.stained-rocks-yellow.name = Stained Rocks Yellow -block.stained-stone-yellow.name = Stained Stone Yellow -block.stained-boulder.name = Stained Boulde block.metal-floor.name = Metal Floor block.metal-floor-2.name = Metal Floor 2 block.metal-floor-3.name = Metal Floor 3 @@ -584,6 +614,7 @@ block.thorium-wall-large.name = Große Thorium-Mauer block.door.name = Tür block.door-large.name = Große Tür block.duo.name = Duo +block.scatter.name = Scatter block.hail.name = Hail block.lancer.name = Lancer block.conveyor.name = Förderband @@ -650,6 +681,7 @@ block.phantom-factory.name = Phantom-Drohnenfabrik block.wraith-factory.name = Wraith Fighter-Fabrik block.ghoul-factory.name = Ghoul Bomber-Fabrik block.dagger-factory.name = Dagger Mech-Fabrik +block.crawler-factory.name = Crawler Mech Factory block.titan-factory.name = Titan Mech-Fabrik block.fortress-factory.name = Fortress Mech-Fabrik block.revenant-factory.name = Revenant Fighter-Fabrik @@ -745,6 +777,7 @@ block.overdrive-projector.description = Erhöht die Geschwindigkeit von nahegele block.force-projector.description = Erzeugt ein sechseckiges Kraftfeld um sich selbst, durch das Blöcke und Einheiten vor Schaden beschützt werden. block.shock-mine.description = Beschädigt Gegner, die auf die Mine laufen. Für Gegener schwer zu sehen. block.duo.description = Ein kleiner, günstiger Geschützturm. +block.scatter.description = A medium-sized anti-air turret. Sprays clumps of lead or scrap flak at enemy units. block.arc.description = Ein kleiner Geschützturm, der Lichtbögen in Richtung des Gegners schießt. block.hail.description = Ein kleiner Artillerie-Geschützturm. block.lancer.description = Ein mittelgroßer Geschützturm, der sich auflädt und Elektrizitätsstrahlen verschießt. diff --git a/core/assets/bundles/bundle_es.properties b/core/assets/bundles/bundle_es.properties index 84a6d51bc5..1405a6e8e8 100644 --- a/core/assets/bundles/bundle_es.properties +++ b/core/assets/bundles/bundle_es.properties @@ -192,11 +192,26 @@ editor.oregen.info = Generación de Minerales: editor.mapinfo = Info del Mapa editor.author = Autor: editor.description = Descripción: +editor.waves = Waves: +waves.title = Waves +waves.remove = Remove +waves.never = +waves.every = every +waves.waves = wave(s) +waves.perspawn = per spawn +waves.to = to +waves.boss = Boss +editor.default = [LIGHT_GRAY] +edit = Edit... editor.name = Nombre: editor.teams = Equipos editor.elevation = Elevación -editor.errorimageload = Error cargando el archivo:\n[accent] {0} -editor.errorimagesave = Error guardando el archivo:\n[accent] {0} +editor.errorload = Error loading file:\n[accent]{0} +editor.errorsave = Error saving file:\n[accent]{0} +editor.errorname = Map has no name defined. +editor.update = Update +editor.randomize = Randomize +editor.apply = Apply editor.generate = Generar editor.resize = Cambiar Tamaño editor.loadmap = Cargar Mapa @@ -225,6 +240,21 @@ editor.mapname = Nombre del Mapa: editor.overwrite = [accent]¡Advertencia!\nEsto sobrescribe un mapa ya existente. editor.overwrite.confirm = [scarlet]¡Advertencia![] Un mapa con ese nombre ya existe. ¿Estás seguro de querer sobrescribirlo? editor.selectmap = Selecciona un mapa para cargar: +filter.distort = Distort +filter.noise = Noise +filter.ore = Ore +filter.rivernoise = River Noise +filter.scatter = Scatter +filter.terrain = Terrain +filter.option.scale = Scale +filter.option.mag = Magnitude +filter.option.threshold = Threshold +filter.option.circle-scale = Circle Scale +filter.option.octaves = Octaves +filter.option.falloff = Falloff +filter.option.floor = Floor +filter.option.wall = Wall +filter.option.ore = Ore width = Ancho: height = Alto: menu = Menu @@ -273,14 +303,9 @@ zone.groundZero.name = Ground Zero zone.craters.name = The Craters zone.frozenForest.name = Frozen Forest zone.ruinousShores.name = Ruinous Shores -zone.crags.name = Crags zone.stainedMountains.name = Stained Mountains -zone.impact0079.name = Impact 0079 zone.desolateRift.name = Desolate Rift -zone.arcticDesert.name = Arctic Desert -zone.dryWastes.name = Dry Wastes zone.nuclearComplex.name = Nuclear Production Complex -zone.moltenFault.name = Molten Fault settings.language = Lenguaje settings.reset = Reiniciar por los de defecto settings.rebind = Reasignar @@ -300,6 +325,7 @@ info.title = [accent]Información error.title = [crimson]Un error ha ocurrido. error.crashtitle = Un error ha ocurrido. blocks.outputspeed = Drill Speed: {0}/s +blocks.efficiency = Efficiency: {0}% blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = Información del Bloque blocks.powerbalance = Power: {0} @@ -307,6 +333,7 @@ blocks.poweroutput = Power Output: {0} blocks.powercapacity = Capacidad de Energía blocks.powershot = Energía/Disparo blocks.targetsair = Apunta al Aire +blocks.items = Items: {0} blocks.itemsmoved = Move Speed blocks.shootrange = Rango blocks.size = Tamaño @@ -369,6 +396,7 @@ category.items = Objetos category.crafting = Fabricación category.shooting = Disparo category.optional = Mejoras Opcionales +setting.animatedwater.name = Animated Water setting.indicators.name = Ally Indicators setting.autotarget.name = Auto apuntado setting.fpscap.name = Máx FPS @@ -523,6 +551,15 @@ mech.ability = [LIGHT_GRAY]Hablidad: {0} liquid.heatcapacity = [LIGHT_GRAY]Capacidad Térmica: {0} liquid.viscosity = [LIGHT_GRAY]Viscosidad: {0} liquid.temperature = [LIGHT_GRAY]Temperatura: {0} +block.grass.name = Grass +block.salt.name = Salt +block.sandrocks.name = Sand Rocks +block.spore-pine.name = Spore Pine +block.shale.name = Shale +block.shale-boulder.name = Shale Boulder +block.moss.name = Moss +block.spore-moss.name = Spore Moss +block.shalerocks.name = Shale Rocks block.scrap-wall.name = Scrap Wall block.scrap-wall-large.name = Large Scrap Wall block.scrap-wall-huge.name = Huge Scrap Wall @@ -557,13 +594,6 @@ block.pine.name = Pine block.white-tree-dead.name = White Tree Dead block.white-tree.name = White Tree block.spore-cluster.name = Spore Cluster -block.stained-rocks.name = Stained Rocks -block.stained-stone.name = Stained Stone -block.stained-rocks-red.name = Stained Rocks Red -block.stained-stone-red.name = Stained Stone Red -block.stained-rocks-yellow.name = Stained Rocks Yellow -block.stained-stone-yellow.name = Stained Stone Yellow -block.stained-boulder.name = Stained Boulde block.metal-floor.name = Metal Floor block.metal-floor-2.name = Metal Floor 2 block.metal-floor-3.name = Metal Floor 3 @@ -584,6 +614,7 @@ block.thorium-wall-large.name = Pared de Torio grande block.door.name = Puerta block.door-large.name = Puerta Larga block.duo.name = Dúo +block.scatter.name = Scatter block.hail.name = Granizo block.lancer.name = Lancero block.conveyor.name = Cinta Transportadora @@ -650,6 +681,7 @@ block.phantom-factory.name = Fábrica de Drones Fantasmales block.wraith-factory.name = Fábrica de Wraith Fighter block.ghoul-factory.name = Fábrica de Ghoul Bomber block.dagger-factory.name = Fábrica de Dagas +block.crawler-factory.name = Crawler Mech Factory block.titan-factory.name = Fábrica de Titanes block.fortress-factory.name = Fábrica de mecanoide Fortress block.revenant-factory.name = Fábrica de Revenant Fighter @@ -745,6 +777,7 @@ block.overdrive-projector.description = Aumenta la velocidad de edificios cercan block.force-projector.description = Crea un área de fuerza hexagonal alrededor de él, protegiendo edificios y unidades dentro de él del daño de las balas. block.shock-mine.description = Daña enemigos que pisan a mina. Casi invisible al enemigo. block.duo.description = Una torre pequeña y barata. +block.scatter.description = A medium-sized anti-air turret. Sprays clumps of lead or scrap flak at enemy units. block.arc.description = Una torre pequeña que disapra electricidad en un arco aleatorio al enemigo. block.hail.description = Una torre de artillería pequeña. block.lancer.description = Una torre de tamaño mediano que dispara rayos cargados eléctricamente. diff --git a/core/assets/bundles/bundle_fr.properties b/core/assets/bundles/bundle_fr.properties index c836a7610b..aaca224a72 100644 --- a/core/assets/bundles/bundle_fr.properties +++ b/core/assets/bundles/bundle_fr.properties @@ -192,11 +192,26 @@ editor.oregen.info = Génération de minerais: editor.mapinfo = Infos sur la carte editor.author = Auteur: editor.description = Description: +editor.waves = Waves: +waves.title = Waves +waves.remove = Remove +waves.never = +waves.every = every +waves.waves = wave(s) +waves.perspawn = per spawn +waves.to = to +waves.boss = Boss +editor.default = [LIGHT_GRAY] +edit = Edit... editor.name = Nom: editor.teams = Équipe editor.elevation = Élevation -editor.errorimageload = Erreur lors du chargement du fichier:\n[accent]{0} -editor.errorimagesave = Erreur lors de la sauvegarde du fichier:\n[accent]{0} +editor.errorload = Error loading file:\n[accent]{0} +editor.errorsave = Error saving file:\n[accent]{0} +editor.errorname = Map has no name defined. +editor.update = Update +editor.randomize = Randomize +editor.apply = Apply editor.generate = Générer editor.resize = Redimensionner editor.loadmap = Charger une carte @@ -225,6 +240,21 @@ editor.mapname = Nom de la carte²: editor.overwrite = [accent]Attention !\nCeci réécrit une carte existante . editor.overwrite.confirm = [scarlet]Attention ![] Une carte avec ce nom existe déjà. Êtes-vous sûr de vouloir la réécrire? editor.selectmap = Séléctionnez une carte: +filter.distort = Distort +filter.noise = Noise +filter.ore = Ore +filter.rivernoise = River Noise +filter.scatter = Scatter +filter.terrain = Terrain +filter.option.scale = Scale +filter.option.mag = Magnitude +filter.option.threshold = Threshold +filter.option.circle-scale = Circle Scale +filter.option.octaves = Octaves +filter.option.falloff = Falloff +filter.option.floor = Floor +filter.option.wall = Wall +filter.option.ore = Ore width = Largeur: height = Hauteur: menu = Menu @@ -273,14 +303,9 @@ zone.groundZero.name = Ground Zero zone.craters.name = The Craters zone.frozenForest.name = Frozen Forest zone.ruinousShores.name = Ruinous Shores -zone.crags.name = Crags zone.stainedMountains.name = Stained Mountains -zone.impact0079.name = Impact 0079 zone.desolateRift.name = Desolate Rift -zone.arcticDesert.name = Arctic Desert -zone.dryWastes.name = Dry Wastes zone.nuclearComplex.name = Nuclear Production Complex -zone.moltenFault.name = Molten Fault settings.language = Langage settings.reset = Valeur par défaut. settings.rebind = Réatttribuer @@ -300,6 +325,7 @@ info.title = Info error.title = [crimson]Une erreur s'est produite error.crashtitle = Une erreur s'est produite blocks.outputspeed = Drill Speed: {0}/s +blocks.efficiency = Efficiency: {0}% blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = Info sur le bloc blocks.powerbalance = Power: {0} @@ -307,6 +333,7 @@ blocks.poweroutput = Power Output: {0} blocks.powercapacity = capacité d'énergie blocks.powershot = Énergie/Tir blocks.targetsair = Cible les unités aériennes +blocks.items = Items: {0} blocks.itemsmoved = Move Speed blocks.shootrange = Portée blocks.size = Taille @@ -369,6 +396,7 @@ category.items = Objets category.crafting = Fabrication category.shooting = Défense category.optional = Optional Enhancements +setting.animatedwater.name = Animated Water setting.indicators.name = Ally Indicators setting.autotarget.name = Visée automatique setting.fpscap.name = Max FPS @@ -523,6 +551,15 @@ mech.ability = [LIGHT_GRAY]Compétence: {0} liquid.heatcapacity = [LIGHT_GRAY]Capacité Thermique: {0} liquid.viscosity = [LIGHT_GRAY]Viscosité: {0} liquid.temperature = [LIGHT_GRAY]Température: {0} +block.grass.name = Grass +block.salt.name = Salt +block.sandrocks.name = Sand Rocks +block.spore-pine.name = Spore Pine +block.shale.name = Shale +block.shale-boulder.name = Shale Boulder +block.moss.name = Moss +block.spore-moss.name = Spore Moss +block.shalerocks.name = Shale Rocks block.scrap-wall.name = Scrap Wall block.scrap-wall-large.name = Large Scrap Wall block.scrap-wall-huge.name = Huge Scrap Wall @@ -557,13 +594,6 @@ block.pine.name = Pine block.white-tree-dead.name = White Tree Dead block.white-tree.name = White Tree block.spore-cluster.name = Spore Cluster -block.stained-rocks.name = Stained Rocks -block.stained-stone.name = Stained Stone -block.stained-rocks-red.name = Stained Rocks Red -block.stained-stone-red.name = Stained Stone Red -block.stained-rocks-yellow.name = Stained Rocks Yellow -block.stained-stone-yellow.name = Stained Stone Yellow -block.stained-boulder.name = Stained Boulde block.metal-floor.name = Metal Floor block.metal-floor-2.name = Metal Floor 2 block.metal-floor-3.name = Metal Floor 3 @@ -584,6 +614,7 @@ block.thorium-wall-large.name = Mur en Thorium large block.door.name = Porte block.door-large.name = Grande porte block.duo.name = Duo +block.scatter.name = Scatter block.hail.name = Hail block.lancer.name = Lancier block.conveyor.name = Convoyeur @@ -650,6 +681,7 @@ block.phantom-factory.name = Usine de "Drones fantômes" block.wraith-factory.name = Usine de "Combattants spectraux" block.ghoul-factory.name = Usine de "Bombardiers goules" block.dagger-factory.name = Usine de "Poignards" +block.crawler-factory.name = Crawler Mech Factory block.titan-factory.name = Usine de "Titans" block.fortress-factory.name = Usine de "Forteresse" block.revenant-factory.name = Usine de "Revenants" @@ -745,6 +777,7 @@ block.overdrive-projector.description = Accélère les batiments autour de lui, block.force-projector.description = Crée un champ de force hexagonal autour de lui qui protège les batiments et les unités à l'intérieur de prendre des dégâts à cause des balles. block.shock-mine.description = Blesse les ennemis qui marchent dessus. Quasiment invisble pour l'ennemi. block.duo.description = une petite tourelle avec un coût faible . +block.scatter.description = A medium-sized anti-air turret. Sprays clumps of lead or scrap flak at enemy units. block.arc.description = une petite tourelle tirant des arcs électrques vers les ennemis. block.hail.description = une petite tourelle d'artillerie. block.lancer.description = une tourelle de taille moyenne tirant des rayons chargés en électricité. diff --git a/core/assets/bundles/bundle_fr_BE.properties b/core/assets/bundles/bundle_fr_BE.properties index ee3b8fe759..661e1e9b3d 100644 --- a/core/assets/bundles/bundle_fr_BE.properties +++ b/core/assets/bundles/bundle_fr_BE.properties @@ -192,11 +192,26 @@ editor.oregen.info = Génération de minerais: editor.mapinfo = Infos sur la carte editor.author = Auteur: editor.description = Description: +editor.waves = Waves: +waves.title = Waves +waves.remove = Remove +waves.never = +waves.every = every +waves.waves = wave(s) +waves.perspawn = per spawn +waves.to = to +waves.boss = Boss +editor.default = [LIGHT_GRAY] +edit = Edit... editor.name = Nom: editor.teams = Équipes editor.elevation = Élévation -editor.errorimageload = Erreur lors du chargement du fichier image:\n[accent]{0} -editor.errorimagesave = Erreur lors de la sauvegarde du fichier image:\n[accent]{0} +editor.errorload = Error loading file:\n[accent]{0} +editor.errorsave = Error saving file:\n[accent]{0} +editor.errorname = Map has no name defined. +editor.update = Update +editor.randomize = Randomize +editor.apply = Apply editor.generate = Générer editor.resize = Redimensionner editor.loadmap = Charger une carte @@ -225,6 +240,21 @@ editor.mapname = Nom de la carte: editor.overwrite = [accent]Attention!\nCela écrasera une carte existante. editor.overwrite.confirm = [scarlet]Attention ![] Une carte avec ce nom existe déjà. Êtes-vous sûr de vouloir la réécrire? editor.selectmap = Sélectionnez une carte à charger: +filter.distort = Distort +filter.noise = Noise +filter.ore = Ore +filter.rivernoise = River Noise +filter.scatter = Scatter +filter.terrain = Terrain +filter.option.scale = Scale +filter.option.mag = Magnitude +filter.option.threshold = Threshold +filter.option.circle-scale = Circle Scale +filter.option.octaves = Octaves +filter.option.falloff = Falloff +filter.option.floor = Floor +filter.option.wall = Wall +filter.option.ore = Ore width = Largeur: height = Hauteur: menu = Menu @@ -273,14 +303,9 @@ zone.groundZero.name = Ground Zero zone.craters.name = The Craters zone.frozenForest.name = Frozen Forest zone.ruinousShores.name = Ruinous Shores -zone.crags.name = Crags zone.stainedMountains.name = Stained Mountains -zone.impact0079.name = Impact 0079 zone.desolateRift.name = Desolate Rift -zone.arcticDesert.name = Arctic Desert -zone.dryWastes.name = Dry Wastes zone.nuclearComplex.name = Nuclear Production Complex -zone.moltenFault.name = Molten Fault settings.language = Langage settings.reset = Valeur par défaut. settings.rebind = Réatttribuer @@ -300,6 +325,7 @@ info.title = Info error.title = [crimson]Une erreur s'est produite error.crashtitle = Une erreur s'est produite blocks.outputspeed = Drill Speed: {0}/s +blocks.efficiency = Efficiency: {0}% blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = Info sur le bloc blocks.powerbalance = Power: {0} @@ -307,6 +333,7 @@ blocks.poweroutput = Power Output: {0} blocks.powercapacity = Capacité d'énergie blocks.powershot = Énergie/Tir blocks.targetsair = Cible les unités aériennes +blocks.items = Items: {0} blocks.itemsmoved = Move Speed blocks.shootrange = Portée blocks.size = Taille @@ -369,6 +396,7 @@ category.items = Objets category.crafting = Fabrication category.shooting = Défense category.optional = Améliorations facultatives +setting.animatedwater.name = Animated Water setting.indicators.name = Indicateurs d'alliés setting.autotarget.name = Visée automatique setting.fpscap.name = Max FPS @@ -523,6 +551,15 @@ mech.ability = [LIGHT_GRAY]Compétence: {0} liquid.heatcapacity = [LIGHT_GRAY]Capacité Thermique {0} liquid.viscosity = [LIGHT_GRAY]Viscosité: {0} liquid.temperature = [LIGHT_GRAY]Température: {0} +block.grass.name = Grass +block.salt.name = Salt +block.sandrocks.name = Sand Rocks +block.spore-pine.name = Spore Pine +block.shale.name = Shale +block.shale-boulder.name = Shale Boulder +block.moss.name = Moss +block.spore-moss.name = Spore Moss +block.shalerocks.name = Shale Rocks block.scrap-wall.name = Scrap Wall block.scrap-wall-large.name = Large Scrap Wall block.scrap-wall-huge.name = Huge Scrap Wall @@ -557,13 +594,6 @@ block.pine.name = Pine block.white-tree-dead.name = White Tree Dead block.white-tree.name = White Tree block.spore-cluster.name = Spore Cluster -block.stained-rocks.name = Stained Rocks -block.stained-stone.name = Stained Stone -block.stained-rocks-red.name = Stained Rocks Red -block.stained-stone-red.name = Stained Stone Red -block.stained-rocks-yellow.name = Stained Rocks Yellow -block.stained-stone-yellow.name = Stained Stone Yellow -block.stained-boulder.name = Stained Boulde block.metal-floor.name = Metal Floor block.metal-floor-2.name = Metal Floor 2 block.metal-floor-3.name = Metal Floor 3 @@ -584,6 +614,7 @@ block.thorium-wall-large.name = Mur en Thorium large block.door.name = Porte block.door-large.name = Grande porte block.duo.name = Duo +block.scatter.name = Scatter block.hail.name = Hail block.lancer.name = Lancer block.conveyor.name = Transporteur @@ -650,6 +681,7 @@ block.phantom-factory.name = Usine de "Drones fantômes" block.wraith-factory.name = Usine de "Combattants spectraux" block.ghoul-factory.name = Usine de "Bombardiers goules" block.dagger-factory.name = Usine de "Poignards" +block.crawler-factory.name = Crawler Mech Factory block.titan-factory.name = Usine de "Titans" block.fortress-factory.name = Usine de "Forteresse" block.revenant-factory.name = Usine de "Revenants" @@ -745,6 +777,7 @@ block.overdrive-projector.description = Augmente la vitesse des bâtiments à pr block.force-projector.description = Crée un champ de force hexagonal autour de lui-même, protégeant les bâtiments et les unités internes des dommages causés par les balles. block.shock-mine.description = Endommage les ennemis qui marchent sur la mine. Presque invisible à l'ennemi. block.duo.description = Une petite tourelle pas chère. +block.scatter.description = A medium-sized anti-air turret. Sprays clumps of lead or scrap flak at enemy units. block.arc.description = Une petite tourelle qui tire de l'électricité dans un arc au hasard vers l'ennemi. block.hail.description = Une petite tourelle d'artillerie. block.lancer.description = Une tourelle de taille moyenne qui tire des faisceaux d’électricité chargés. diff --git a/core/assets/bundles/bundle_in_ID.properties b/core/assets/bundles/bundle_in_ID.properties index d591dce885..db4f8a61b2 100644 --- a/core/assets/bundles/bundle_in_ID.properties +++ b/core/assets/bundles/bundle_in_ID.properties @@ -192,11 +192,26 @@ editor.oregen.info = Ore Generation: editor.mapinfo = Map Info editor.author = Author: editor.description = Description: +editor.waves = Waves: +waves.title = Waves +waves.remove = Remove +waves.never = +waves.every = every +waves.waves = wave(s) +waves.perspawn = per spawn +waves.to = to +waves.boss = Boss +editor.default = [LIGHT_GRAY] +edit = Edit... editor.name = Name: editor.teams = Teams editor.elevation = Elevation -editor.errorimageload = Kesalahan saat memuat file gambar:\n[accent]{0} -editor.errorimagesave = Kesalahan saat menyimpan file gambar:\n[accent]{0} +editor.errorload = Error loading file:\n[accent]{0} +editor.errorsave = Error saving file:\n[accent]{0} +editor.errorname = Map has no name defined. +editor.update = Update +editor.randomize = Randomize +editor.apply = Apply editor.generate = Hasilkan editor.resize = Ubah ukuran editor.loadmap = Buka Peta @@ -225,6 +240,21 @@ editor.mapname = Nama Peta: editor.overwrite = [accent]Peringatan!\nIni akan mengganti peta yang ada. editor.overwrite.confirm = [scarlet]Warning![] A map with this name already exists. Are you sure you want to overwrite it? editor.selectmap = Pilih peta yang akan dimuat: +filter.distort = Distort +filter.noise = Noise +filter.ore = Ore +filter.rivernoise = River Noise +filter.scatter = Scatter +filter.terrain = Terrain +filter.option.scale = Scale +filter.option.mag = Magnitude +filter.option.threshold = Threshold +filter.option.circle-scale = Circle Scale +filter.option.octaves = Octaves +filter.option.falloff = Falloff +filter.option.floor = Floor +filter.option.wall = Wall +filter.option.ore = Ore width = Lebar: height = Tinggi: menu = Menu @@ -273,14 +303,9 @@ zone.groundZero.name = Ground Zero zone.craters.name = The Craters zone.frozenForest.name = Frozen Forest zone.ruinousShores.name = Ruinous Shores -zone.crags.name = Crags zone.stainedMountains.name = Stained Mountains -zone.impact0079.name = Impact 0079 zone.desolateRift.name = Desolate Rift -zone.arcticDesert.name = Arctic Desert -zone.dryWastes.name = Dry Wastes zone.nuclearComplex.name = Nuclear Production Complex -zone.moltenFault.name = Molten Fault settings.language = Bahasa settings.reset = Atur ulang ke Default settings.rebind = Rebind @@ -300,6 +325,7 @@ info.title = [accent]Info error.title = [crimson]Telah terjadi kesalahan error.crashtitle = Telah terjadi kesalahan blocks.outputspeed = Drill Speed: {0}/s +blocks.efficiency = Efficiency: {0}% blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = Info Blok blocks.powerbalance = Power: {0} @@ -307,6 +333,7 @@ blocks.poweroutput = Power Output: {0} blocks.powercapacity = Kapasitas Tenaga blocks.powershot = Tenaga/tembakan blocks.targetsair = Targets Air +blocks.items = Items: {0} blocks.itemsmoved = Move Speed blocks.shootrange = Range blocks.size = Ukuran @@ -369,6 +396,7 @@ category.items = Items category.crafting = Crafting category.shooting = Shooting category.optional = Optional Enhancements +setting.animatedwater.name = Animated Water setting.indicators.name = Ally Indicators setting.autotarget.name = Auto-Target setting.fpscap.name = Max FPS @@ -523,6 +551,15 @@ mech.ability = [LIGHT_GRAY]Ability: {0} liquid.heatcapacity = [LIGHT_GRAY]Heat Capacity: {0} liquid.viscosity = [LIGHT_GRAY]Viscosity: {0} liquid.temperature = [LIGHT_GRAY]Temperature: {0} +block.grass.name = Grass +block.salt.name = Salt +block.sandrocks.name = Sand Rocks +block.spore-pine.name = Spore Pine +block.shale.name = Shale +block.shale-boulder.name = Shale Boulder +block.moss.name = Moss +block.spore-moss.name = Spore Moss +block.shalerocks.name = Shale Rocks block.scrap-wall.name = Scrap Wall block.scrap-wall-large.name = Large Scrap Wall block.scrap-wall-huge.name = Huge Scrap Wall @@ -557,13 +594,6 @@ block.pine.name = Pine block.white-tree-dead.name = White Tree Dead block.white-tree.name = White Tree block.spore-cluster.name = Spore Cluster -block.stained-rocks.name = Stained Rocks -block.stained-stone.name = Stained Stone -block.stained-rocks-red.name = Stained Rocks Red -block.stained-stone-red.name = Stained Stone Red -block.stained-rocks-yellow.name = Stained Rocks Yellow -block.stained-stone-yellow.name = Stained Stone Yellow -block.stained-boulder.name = Stained Boulde block.metal-floor.name = Metal Floor block.metal-floor-2.name = Metal Floor 2 block.metal-floor-3.name = Metal Floor 3 @@ -584,6 +614,7 @@ block.thorium-wall-large.name = Large Thorium Wall block.door.name = pintu block.door-large.name = pintu besar block.duo.name = Duo +block.scatter.name = Scatter block.hail.name = Hail block.lancer.name = Lancer block.conveyor.name = konveyor @@ -650,6 +681,7 @@ block.phantom-factory.name = Phantom Drone Factory block.wraith-factory.name = Wraith Fighter Factory block.ghoul-factory.name = Ghoul Bomber Factory block.dagger-factory.name = Dagger Mech Factory +block.crawler-factory.name = Crawler Mech Factory block.titan-factory.name = Titan Mech Factory block.fortress-factory.name = Fortress Mech Factory block.revenant-factory.name = Revenant Fighter Factory @@ -745,6 +777,7 @@ block.overdrive-projector.description = Increases the speed of nearby buildings block.force-projector.description = Creates a hexagonal force field around itself, protecting buildings and units inside from damage through bullets. block.shock-mine.description = Damages enemies stepping on the mine. Nearly invisible to the enemy. block.duo.description = A small, cheap turret. +block.scatter.description = A medium-sized anti-air turret. Sprays clumps of lead or scrap flak at enemy units. block.arc.description = A small turret which shoots electricity in a random arc towards the enemy. block.hail.description = A small artillery turret. block.lancer.description = A medium-sized turret which shoots charged electricity beams. diff --git a/core/assets/bundles/bundle_it.properties b/core/assets/bundles/bundle_it.properties index 54539615aa..d143f6005e 100644 --- a/core/assets/bundles/bundle_it.properties +++ b/core/assets/bundles/bundle_it.properties @@ -192,11 +192,26 @@ editor.oregen.info = Generazione dei minerali: editor.mapinfo = Informazioni mappa editor.author = Autore: editor.description = Descrizione: +editor.waves = Waves: +waves.title = Waves +waves.remove = Remove +waves.never = +waves.every = every +waves.waves = wave(s) +waves.perspawn = per spawn +waves.to = to +waves.boss = Boss +editor.default = [LIGHT_GRAY] +edit = Edit... editor.name = Nome: editor.teams = Squadre editor.elevation = Elevazione -editor.errorimageload = Errore durante il caricamento del file immagine:\n [accent]{0} -editor.errorimagesave = Errore durante il salvataggio del file immagine:\n [accent]{0} +editor.errorload = Error loading file:\n[accent]{0} +editor.errorsave = Error saving file:\n[accent]{0} +editor.errorname = Map has no name defined. +editor.update = Update +editor.randomize = Randomize +editor.apply = Apply editor.generate = Genera editor.resize = Ridimensiona editor.loadmap = Carica\nmappa @@ -225,6 +240,21 @@ editor.mapname = Nome Mappa: editor.overwrite = [Accent]Attenzione!\nQuesto sovrascrive una mappa esistente. editor.overwrite.confirm = [scarlet]Attenzione![] Una mappa con questo nome esiste già. Sei sicuro di volerla sovrascrivere? editor.selectmap = Seleziona una mappa da caricare: +filter.distort = Distort +filter.noise = Noise +filter.ore = Ore +filter.rivernoise = River Noise +filter.scatter = Scatter +filter.terrain = Terrain +filter.option.scale = Scale +filter.option.mag = Magnitude +filter.option.threshold = Threshold +filter.option.circle-scale = Circle Scale +filter.option.octaves = Octaves +filter.option.falloff = Falloff +filter.option.floor = Floor +filter.option.wall = Wall +filter.option.ore = Ore width = Larghezza: height = Altezza: menu = Menu @@ -273,14 +303,9 @@ zone.groundZero.name = Ground Zero zone.craters.name = The Craters zone.frozenForest.name = Frozen Forest zone.ruinousShores.name = Ruinous Shores -zone.crags.name = Crags zone.stainedMountains.name = Stained Mountains -zone.impact0079.name = Impact 0079 zone.desolateRift.name = Desolate Rift -zone.arcticDesert.name = Arctic Desert -zone.dryWastes.name = Dry Wastes zone.nuclearComplex.name = Nuclear Production Complex -zone.moltenFault.name = Molten Fault settings.language = Lingua settings.reset = Resetta Alle Impostazioni Predefinite settings.rebind = Reinposta @@ -300,6 +325,7 @@ info.title = [accent] Info error.title = [crimson]Si è verificato un errore error.crashtitle = Si è verificato un errore blocks.outputspeed = Drill Speed: {0}/s +blocks.efficiency = Efficiency: {0}% blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = info sul blocco blocks.powerbalance = Power: {0} @@ -307,6 +333,7 @@ blocks.poweroutput = Power Output: {0} blocks.powercapacity = Capacità Energetica blocks.powershot = Danno/Colpo blocks.targetsair = Attacca nemici aerei +blocks.items = Items: {0} blocks.itemsmoved = Move Speed blocks.shootrange = Raggio blocks.size = Grandezza @@ -369,6 +396,7 @@ category.items = Oggetti category.crafting = Produzione category.shooting = Potenza di fuoco category.optional = Optional Enhancements +setting.animatedwater.name = Animated Water setting.indicators.name = Ally Indicators setting.autotarget.name = Auto-Target setting.fpscap.name = Limite FPS @@ -523,6 +551,15 @@ mech.ability = [LIGHT_GRAY]Abilità: {0} liquid.heatcapacity = [LIGHT_GRAY]Capacità calorifica: {0} liquid.viscosity = [LIGHT_GRAY]Viscosità: {0} liquid.temperature = [LIGHT_GRAY]Temperatura: {0} +block.grass.name = Grass +block.salt.name = Salt +block.sandrocks.name = Sand Rocks +block.spore-pine.name = Spore Pine +block.shale.name = Shale +block.shale-boulder.name = Shale Boulder +block.moss.name = Moss +block.spore-moss.name = Spore Moss +block.shalerocks.name = Shale Rocks block.scrap-wall.name = Scrap Wall block.scrap-wall-large.name = Large Scrap Wall block.scrap-wall-huge.name = Huge Scrap Wall @@ -557,13 +594,6 @@ block.pine.name = Pine block.white-tree-dead.name = White Tree Dead block.white-tree.name = White Tree block.spore-cluster.name = Spore Cluster -block.stained-rocks.name = Stained Rocks -block.stained-stone.name = Stained Stone -block.stained-rocks-red.name = Stained Rocks Red -block.stained-stone-red.name = Stained Stone Red -block.stained-rocks-yellow.name = Stained Rocks Yellow -block.stained-stone-yellow.name = Stained Stone Yellow -block.stained-boulder.name = Stained Boulde block.metal-floor.name = Metal Floor block.metal-floor-2.name = Metal Floor 2 block.metal-floor-3.name = Metal Floor 3 @@ -584,6 +614,7 @@ block.thorium-wall-large.name = Muro grande di torio block.door.name = porta block.door-large.name = Porta grande block.duo.name = Duo +block.scatter.name = Scatter block.hail.name = Bombardiere block.lancer.name = Idrogetto block.conveyor.name = trasportatore @@ -650,6 +681,7 @@ block.phantom-factory.name = Phantom Drone Factory block.wraith-factory.name = Wraith Fighter Factory block.ghoul-factory.name = Ghoul Bomber Factory block.dagger-factory.name = Dagger Mech Factory +block.crawler-factory.name = Crawler Mech Factory block.titan-factory.name = Titan Mech Factory block.fortress-factory.name = Fortress Mech Factory block.revenant-factory.name = Revenant Fighter Factory @@ -745,6 +777,7 @@ block.overdrive-projector.description = Increases the speed of nearby buildings block.force-projector.description = Creates a hexagonal force field around itself, protecting buildings and units inside from damage through bullets. block.shock-mine.description = Damages enemies stepping on the mine. Nearly invisible to the enemy. block.duo.description = A small, cheap turret. +block.scatter.description = A medium-sized anti-air turret. Sprays clumps of lead or scrap flak at enemy units. block.arc.description = A small turret which shoots electricity in a random arc towards the enemy. block.hail.description = A small artillery turret. block.lancer.description = A medium-sized turret which shoots charged electricity beams. diff --git a/core/assets/bundles/bundle_ja.properties b/core/assets/bundles/bundle_ja.properties index 0fbd94d95a..8ef5d5a37d 100644 --- a/core/assets/bundles/bundle_ja.properties +++ b/core/assets/bundles/bundle_ja.properties @@ -194,11 +194,26 @@ editor.oregen.info = 鉱石の生成: editor.mapinfo = マップ情報 editor.author = 作者: editor.description = 説明: +editor.waves = Waves: +waves.title = Waves +waves.remove = Remove +waves.never = +waves.every = every +waves.waves = wave(s) +waves.perspawn = per spawn +waves.to = to +waves.boss = Boss +editor.default = [LIGHT_GRAY] +edit = Edit... editor.name = 名前: editor.teams = チーム editor.elevation = 標高 -editor.errorimageload = ファイルの読み込みエラー:\n[accent]{0} -editor.errorimagesave = ファイルの保存エラー:\n[accent]{0} +editor.errorload = Error loading file:\n[accent]{0} +editor.errorsave = Error saving file:\n[accent]{0} +editor.errorname = Map has no name defined. +editor.update = Update +editor.randomize = Randomize +editor.apply = Apply editor.generate = 生成 editor.resize = リサイズ editor.loadmap = マップを読み込む @@ -227,6 +242,21 @@ editor.mapname = マップ名: editor.overwrite = [accent]警告!\n存在するマップを上書きします。 editor.overwrite.confirm = [scarlet]警告![] この名前のマップがすでに存在します。上書きしてもよろしいですか? editor.selectmap = 読み込むマップを選択: +filter.distort = Distort +filter.noise = Noise +filter.ore = Ore +filter.rivernoise = River Noise +filter.scatter = Scatter +filter.terrain = Terrain +filter.option.scale = Scale +filter.option.mag = Magnitude +filter.option.threshold = Threshold +filter.option.circle-scale = Circle Scale +filter.option.octaves = Octaves +filter.option.falloff = Falloff +filter.option.floor = Floor +filter.option.wall = Wall +filter.option.ore = Ore width = 幅: height = 高さ: menu = メニュー @@ -271,18 +301,13 @@ error.alreadyconnected = すでに接続されています。 error.mapnotfound = マップファイルが見つかりません! error.io = ネットワークエラーです。 error.any = 不明なネットワークエラーです。 -zone.groundZero.name = グラウンド・ゼロ -zone.craters.name = ザ・クレーター -zone.frozenForest.name = フローズン・フォレスト -zone.ruinousShores.name = ルーイナス・ショアーズ -zone.crags.name = クライグス -zone.stainedMountains.name = ステインド・マウンテン -zone.impact.name = インパクト 0079 -zone.desolateRift.name = ディサレット・リフト -zone.arcticDesert.name = アークティック・デザート -zone.dryWastes.name = ドライ・ウィースト -zone.nuclearComplex.name = ニュークリア・プロダクション・コンプレックス -zone.moltenFault.name = モールテン・フォート +zone.groundZero.name = Ground Zero +zone.craters.name = The Craters +zone.frozenForest.name = Frozen Forest +zone.ruinousShores.name = Ruinous Shores +zone.stainedMountains.name = Stained Mountains +zone.desolateRift.name = Desolate Rift +zone.nuclearComplex.name = Nuclear Production Complex settings.language = 言語 settings.reset = デフォルトにリセット settings.rebind = 再設定 @@ -301,7 +326,8 @@ no = いいえ info.title = 情報 error.title = [crimson]エラーが発生しました error.crashtitle = エラーが発生しました -blocks.outputspeed = 採掘速度: {0}/s +blocks.outputspeed = Drill Speed: {0}/s +blocks.efficiency = Efficiency: {0}% blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = ブロック情報 blocks.powerbalance = 電力: {0} @@ -309,7 +335,8 @@ blocks.poweroutput = 電力発電量: {0} blocks.powercapacity = 電力容量 blocks.powershot = 電力/ショット blocks.targetsair = 対空攻撃 -blocks.itemsmoved = 輸送速度 +blocks.items = Items: {0} +blocks.itemsmoved = Move Speed blocks.shootrange = 範囲 blocks.size = 大きさ blocks.liquidcapacity = 液体容量 @@ -371,6 +398,7 @@ category.items = アイテム category.crafting = 製作速度 category.shooting = 攻撃速度 category.optional = 機能強化オプション +setting.animatedwater.name = Animated Water setting.indicators.name = 味方の方角表示 setting.autotarget.name = 自動ターゲット setting.fpscap.name = 最大FPS @@ -525,13 +553,22 @@ mech.ability = [LIGHT_GRAY]能力: {0} liquid.heatcapacity = [LIGHT_GRAY]熱容量: {0} liquid.viscosity = [LIGHT_GRAY]粘度: {0} liquid.temperature = [LIGHT_GRAY]温度: {0} -block.scrap-wall.name = スクラップの壁 -block.scrap-wall-large.name = 大きなスクラップの壁 -block.scrap-wall-huge.name = とても大きなスクラップの壁 -block.scrap-wall-gigantic.name = 巨大なスクラップの壁 -block.thruster.name = スラスター -block.kiln.name = かまど -block.kiln.description = 砂と鉛を溶かしてメタガラスを生成します。少量の電力が必要です。 +block.grass.name = Grass +block.salt.name = Salt +block.sandrocks.name = Sand Rocks +block.spore-pine.name = Spore Pine +block.shale.name = Shale +block.shale-boulder.name = Shale Boulder +block.moss.name = Moss +block.spore-moss.name = Spore Moss +block.shalerocks.name = Shale Rocks +block.scrap-wall.name = Scrap Wall +block.scrap-wall-large.name = Large Scrap Wall +block.scrap-wall-huge.name = Huge Scrap Wall +block.scrap-wall-gigantic.name = Gigantic Scrap Wall +block.thruster.name = Thruster +block.kiln.name = Kiln +block.kiln.description = Smelts sand and lead into metaglass. Requires small amounts of power. block.graphite-press.name = Graphite Press block.multi-press.name = Multi-Press block.constructing = {0}\n[LIGHT_GRAY](建設中) @@ -559,13 +596,6 @@ block.pine.name = Pine block.white-tree-dead.name = White Tree Dead block.white-tree.name = White Tree block.spore-cluster.name = Spore Cluster -block.stained-rocks.name = Stained Rocks -block.stained-stone.name = Stained Stone -block.stained-rocks-red.name = Stained Rocks Red -block.stained-stone-red.name = Stained Stone Red -block.stained-rocks-yellow.name = Stained Rocks Yellow -block.stained-stone-yellow.name = Stained Stone Yellow -block.stained-boulder.name = Stained Boulde block.metal-floor.name = Metal Floor block.metal-floor-2.name = Metal Floor 2 block.metal-floor-3.name = Metal Floor 3 @@ -586,6 +616,7 @@ block.thorium-wall-large.name = 大きなトリウムの壁 block.door.name = ドア block.door-large.name = 大きなドア block.duo.name = デュオ +block.scatter.name = Scatter block.hail.name = ヘイル block.lancer.name = ランサー block.conveyor.name = コンベアー @@ -652,6 +683,7 @@ block.phantom-factory.name = ファントムドローン製造機 block.wraith-factory.name = レースファイター製造機 block.ghoul-factory.name = グールボンバー製造機 block.dagger-factory.name = ダガーユニット製造機 +block.crawler-factory.name = Crawler Mech Factory block.titan-factory.name = タイタンユニット製造機 block.fortress-factory.name = フォートレスユニット製造機 block.revenant-factory.name = レベナントファイター製造機 @@ -747,6 +779,7 @@ block.overdrive-projector.description = ドリルやコンベアなど、近く block.force-projector.description = 周囲に六角形の力場を作り出し、内部の建造物やユニットなどを守ります。 block.shock-mine.description = 敵が踏むと、ダメージを与えます。敵には見えません。 block.duo.description = 小さく安価なターレットです。 +block.scatter.description = A medium-sized anti-air turret. Sprays clumps of lead or scrap flak at enemy units. block.arc.description = 小型の電撃ターレットです。敵に向かってランダムな半円状に電撃を放ちます。 block.hail.description = 小型の砲撃ターレットです。 block.lancer.description = チャージビームを放つ中型ターレットです。 diff --git a/core/assets/bundles/bundle_ko.properties b/core/assets/bundles/bundle_ko.properties index 169cd42444..869256d1ba 100644 --- a/core/assets/bundles/bundle_ko.properties +++ b/core/assets/bundles/bundle_ko.properties @@ -1,25 +1,25 @@ credits.text = Created by [ROYAL]Anuken[] - [SKY]anukendev@gmail.com[] credits = 제작자 contributors = 번역 및 기여자들 -discord = Mindustry Discord 에 참여 해 보세요! -link.discord.description = 공식 Mindustry Discord 채팅방 +discord = mindustry discord 에 참여 해 보세요! +link.discord.description = 공식 mindustry discrod 채팅방 link.github.description = 게임 소스코드 -link.dev-builds.description = 개발중인 빌드 -link.trello.description = 다음 출시될 기능들을 게시한 공식 Trello 보드 +link.dev-builds.description = 불안정한 개발 빌드들 +link.trello.description = 다음 출시될 기능들을 게시판 공식 Trello 보드 link.itch.io.description = PC 버전 다운로드와 HTML5 버전이 있는 itch.io 사이트 link.google-play.description = Google Play 스토어 정보 -link.wiki.description = 공식 Mindustry 위키 (영어) -linkfail = 링크를 여는데 실패했습니다! URL이 기기의 클립보드에 복사되었습니다.\n +link.wiki.description = 공식 Mindustry 위키 +linkfail = 링크를 여는데 실패했습니다!\nURL이 기기의 클립보드에 복사되었습니다. screenshot = 화면 캡쳐가 {0} 경로에 저장되었습니다. -gameover = 코어가 터졌습니다. 게임 오버! +gameover = 게임 오버 gameover.pvp = [accent]{0}[] 팀이 승리했습니다! -highscore = [yellow]최고점수 달성! -stat.wave = 단계 성공: [accent]{0} -stat.enemiesDestroyed = 적 파괴: [accent]{0} -stat.built = 건물 건설: [accent]{0} -stat.destroyed = 건물 파괴됨: [accent]{0} -stat.deconstructed = 건물 해체: [accent]{0} -stat.delivered = 획득한 자원 : +highscore = [accent]최고점수 달성! +stat.wave = 웨이브 성공:[accent]{0} +stat.enemiesDestroyed = 파괴한 적 수:[accent]{0} +stat.built = 건설한 건물 수:[accent]{0} +stat.destroyed = 파괴된 건물 수:[accent]{0} +stat.deconstructed = 해체한 건물 수:[accent]{0} +stat.delivered = 획득한 자원: stat.rank = 최종 기록: [accent]{0} map.delete = 정말로 "[accent]{0}[]" 맵을 삭제하시겠습니까?\n level.highscore = 최고 점수: [accent]{0} @@ -28,12 +28,12 @@ level.mode = 게임 모드 : construction.desktop = PC 에서의 조작 방법이 변경되었습니다.\n블록 선택을 해제하거나 건설을 중지하려면 [accent]스페이스 바[]를 누르세요.\n construction.title = PC 에서의 조작 방법이 변경되었습니다. construction = [accent]블록 배치 모드[]를 선택하셨습니다.\n\n블록을 설치하고 싶으면, 자신의 건설 가능 범위 내에서 간단히 탭 하면 됩니다.\n일부 블록을 선택한 후에 확인 버튼을 누르면 배가 배치 작업을 진행할 것입니다.\n\n- [accent]블록을 삭제[]하고 싶다면 배치하고 싶은 영역을 탭 하세요. \n- [accent]블록을 넓게 배치[]하고 싶다면 배치하고 싶은 시작 영역을 길게 누르며 드래그 하면 됩니다.\n- [accent]블록을 한줄로 배치[]하고 싶다면 배치하고 싶은 시작 영역을 한번 탭 하고 길게 누르면서 드래그 하면 됩니다. \n- [accent]블록 배치 모드를 취소[]하고 싶다면 화면 하단 왼쪽에 있는 X 버튼을 누르면 됩니다. -deconstruction.title = 블록 삭제 안내서 -deconstruction = [accent]블록 삭제 모드[]를 선택하셨습니다\n\n블록을 삭제하고 싶다면, 자신의 건설 가능 범위 내에서 간단히 탭 하면 됩니다.\n일부 블록을 선택한 후에 확인 버튼을 누르면 배가 파괴 작업을 진행할 것입니다.\n\n- [accent]블록을 삭제[]하고 싶다면 배치하고 싶은 영역을 탭 하세요\n- [accent]블록을 넓은 범위로 삭제[]하고 싶다면 배치하고 싶은 시작 영역을 길게 누르며 드래그 하면 됩니다.\n- [accent]블록 삭제 모드를 취소[]하고 싶다면 화면 하단 왼쪽에 있는 X 버튼을 누르면 됩니다. +deconstruction.title = 블록 해체 안내서 +deconstruction = [accent]블록 해체 모드[]를 선택하셨습니다\n\n블록을 삭제하고 싶다면, 자신의 건설 가능 범위 내에서 간단히 탭 하면 됩니다.\n일부 블록을 선택한 후에 확인 버튼을 누르면 배가 파괴 작업을 진행할 것입니다.\n\n- [accent]블록을 삭제[]하고 싶다면 배치하고 싶은 영역을 탭 하세요\n- [accent]블록을 넓은 범위로 삭제[]하고 싶다면 배치하고 싶은 시작 영역을 길게 누르며 드래그 하면 됩니다.\n- [accent]블록 삭제 모드를 취소[]하고 싶다면 화면 하단 왼쪽에 있는 X 버튼을 누르면 됩니다. showagain = 다음 세션에서 이 메세지를 표시하지 않습니다 coreattack = < 코어가 공격받고 있습니다! > -nearpoint = [[ [scarlet]스폰 지점에서 나가세요[] ]\n모든 유닛 및 건물 파괴 임박 -outofbounds = [[출입 금지 구역]\n[]{0}초후 파괴됩니다. +nearpoint = [[ [scarlet]드롭 지점에서 나가세요[] ]\n모든 유닛 및 건물 파괴 임박 +outofbounds = [[ 출입 금지 구역 ]\n[]{0}초후 건물이 해체됩니다. database = 코어 데이터베이스 savegame = 게임 저장 loadgame = 게임 불러오기 @@ -52,7 +52,7 @@ name = 이름 : noname = 먼저 [accent] 플레이어 이름[] 을 설정하세요. filename = 파일 이름 : unlocked = 새 블록 잠금 해제됨 -completed = [accent]성공 +completed = [accent]연구됨 techtree = 기술 트리 research.list = [LIGHT_GRAY]연구: research = 연구 @@ -64,14 +64,14 @@ server.kicked.kick = 서버에서 추방되었습니다! server.kicked.serverClose = 서버 종료됨. server.kicked.clientOutdated = 오래된 버전의 클라이언트 입니다! 게임을 업데이트 하세요! server.kicked.serverOutdated = 오래된 버전의 서버입니다! 서버 호스트 관리자에게 문의하세요! -server.kicked.banned = 서버 규칙 위반으로 인해, 지금부터 영원히 서버에 접속할 수 없습니다. -server.kicked.recentKick = 방금 추방처리 되었습니다.\n잠시 기다린 후에 접속 해 주세요.\n참고: [accent]계속해서 접속을 시도하면 강퇴 시간이 길어집니다. +server.kicked.banned = 서버 규칙 위반으로 인해, 이제 당신은 영원히 이 서버를 플레이 하실 수 없습니다. +server.kicked.recentKick = 방금 추방처리 되었습니다.\n잠시 기다린 후에 접속 해 주세요. server.kicked.nameInUse = 이 닉네임이 이미 서버에서 사용중입니다. server.kicked.nameEmpty = 닉네임에는 반드시 영어 또는 숫자가 있어야 합니다. server.kicked.idInUse = 이미 서버에 접속중입니다! 다중 계정은 허용되지 않습니다. server.kicked.customClient = 이 서버는 직접 빌드한 버전을 지원하지 않습니다. 공식 버전을 사용하세요. -server.kicked.gameover = 게임 오버로 인해 서버에서 추방되었습니다. -host.info = [accent]호스트[] 버튼은 현재 네트워크의 [scarlet]6567[] 포트를 사용합니다.\n[LIGHY_GRAY]같은 Wi-Fi 또는 로컬 네트워크[] 에서 서버 목록을 볼 수 있습니다.\n\n만약 플레이어들이 이 IP를 통해 어디에서나 연결할 수 있게 하고 싶다면, 공유기 설정에서 [accent]포트 포워딩[]을 해야 합니다.\n\n[LIGHT_GRAY]참고: LAN 게임 연결에 문제가 있는 사람이 있다면, 방화벽 설정에서 Mindustry 가 로컬 네트워크에 액세스하도록 허용했는지 확인 해 주세요. +server.kicked.gameover = 게임 오버! +host.info = [accent]호스트[] 버튼은 현재 네트워크의 [scarlet]6567[] 포트를 사용합니다.\n[LIGHT_GRAY]같은 Wi-Fi 또는 로컬 네트워크[] 에서 서버 목록을 볼 수 있습니다.\n\n만약 플레이어들이 이 IP를 통해 어디에서나 연결할 수 있게 하고 싶다면, 공유기 설정에서 [accent]포트 포워딩[]을 해야 합니다.\n\n[LIGHT_GRAY]참고: LAN 게임 연결에 문제가 있는 사람이 있다면, 방화벽 설정에서 Mindustry 가 로컬 네트워크에 액세스하도록 허용했는지 확인 해 주세요. join.info = 여기서 [accent]서버 IP[]를 입력하여 다른 서버에 접속할 수 있습니다.\n또는 [accent]로컬 네트워크(LAN)[] 서버를 검색하여 접속할 수 있습니다.\nLAN 및 WAN 멀티 플레이어 모두 지원됩니다.\n\n[LIGHT_GRAY]참고:여기에서는 자동으로 글로벌 서버를 추가하지 않습니다. IP로 다른 사람의 서버에 접속할려면 서버장에게 IP를 요청해야 합니다. hostserver = 서버 열기 hostserver.mobile = 서버\n열기 @@ -93,7 +93,7 @@ trace.structureblocksbroken = 구조 블록 파괴 수: [accent]{0} trace.lastblockbroken = 마지막으로 파괴한 블록: [accent]{0} trace.totalblocksplaced = 총 설치한 블록 개수: [accent]{0} trace.lastblockplaced = 마지막으로 설치한 블록: [accent]{0} -invalidid = 잘못된 클라이언트 ID 입니다! 공식 Mindustry Discord 으로 버그 보고서를 제출 해 주세요. +invalidid = 잘못된 클라이언트 ID 입니다! 버그 보고서를 제출 해 주세요. server.bans = 차단된 유저 server.bans.none = 차단된 플레이어가 없습니다. server.admins = 관리자 @@ -103,7 +103,7 @@ server.delete = 이 서버를 삭제 하시겠습니까? server.hostname = 호스트: {0} server.edit = 서버 수정 server.outdated = [crimson]서버 버전이 낮습니다![] -server.outdated.client = [Crimson]클라이언트 버전이 낮습니다![] +server.outdated.client = [crimson]클라이언트 버전이 낮습니다![] server.version = [lightgray]서버 버전: {0} {1} server.custombuild = [yellow]커스텀 서버 confirmban = 이 플레이어를 차단하시겠습니까? @@ -112,15 +112,15 @@ confirmunban = 이 플레이어를 차단해제 하시겠습니까? confirmadmin = 이 플레이어를 관리자로 만들겠습니까? confirmunadmin = 이 플레이어를 일반 유저로 만들겠습니까? joingame.title = 게임 참가 -joingame.ip = IP: +joingame.ip = 주소: disconnect = 서버와 연결이 해제되었습니다. -disconnect.data = 맵 데이터를 받아오는데 실패했습니다. +disconnect.data = 맵 데이터를 받아오는데 실패했습니다! connecting = [accent]연결중... connecting.data = [accent]맵 데이터 다운로드중... -server.port = 포트 : +server.port = 포트: server.addressinuse = 이 주소는 이미 사용중입니다! server.invalidport = 포트 번호가 잘못되었습니다. -server.error = [crimson]{0}[accent]서버를 여는데 오류가 발생했습니다.[] +server.error = [accent]{0}[crimson]서버를 여는데 오류가 발생했습니다. save.old = 이 저장파일은 이전 버전의 게임용이며, 지금은 사용할 수 없습니다. \n\n[LIGHT_GRAY]4.0 정식때 이전 게임버전에서 만든 저장파일과 호환됩니다. save.new = 새로 저장 save.overwrite = 이 저장 슬롯을 덮어씌우겠습니까? @@ -135,9 +135,9 @@ save.import.invalid = [accent]파일이 잘못되었습니다! save.import.fail = [crimson]저장파일을 불러오지 못함: [accent]{0} save.export.fail = [crimson]저장파일을 내보내지 못함: [accent]{0} save.import = 저장파일 불러오기 -save.newslot = 저장 파일이름 : +save.newslot = 저장 파일이름: save.rename = 이름 변경 -save.rename.text = 새 이름 : +save.rename.text = 새 이름: selectslot = 저장슬롯을 선택하십시오. slot = [accent]{0}번째 슬롯 save.corrupted = [accent]세이브 파일이 손상되었거나 잘못된 파일입니다! 만약 게임을 업데이트 했다면 이것은 아마 저장 형식 변경일 것이고, 이것은 버그가 [scarlet]아닙니다[]. @@ -146,7 +146,7 @@ on = 켜기 off = 끄기 save.autosave = 자동저장: {0} save.map = 맵: {0} -save.wave = 단계[]{0} +save.wave = 웨이브 {0} save.difficulty = 난이도: {0} save.date = 마지막 저장날짜: {0} save.playtime = 플레이시간: {0} @@ -164,13 +164,13 @@ changelog.title = 변경사항 changelog.loading = 변경사항 가져오는중... changelog.error.android = [accent]게임 변경사항은 가끔 Android 4.4 이하에서 작동하지 않습니다. 이것은 내부 Android 버그 때문입니다. changelog.error.ios = [accent]현재 iOS에서는 변경 사항을 지원하지 않습니다. -changelog.error = [scarlet]게임 변경사항을 가져오는 중 오류가 발생했습니다![]\n인터넷 연결을 확인하십시오. -changelog.current = [accent][[현재 버전] +changelog.error = [scarlet]게임 변경사항을 가져오는 중 오류가 발생했습니다!\n인터넷 연결을 확인하십시오. +changelog.current = [yellow][[현재 버전] changelog.latest = [accent][[최신 버전] loading = [accent]불러오는중... saving = [accent]저장중... -wave = [accent]{0} 단계 -wave.waiting = 남은 시간: [green]{0}초[] +wave = [accent]웨이브 {0} +wave.waiting = [green]{0}초[]후 웨이브 시작 waiting = [LIGHT_GRAY]대기중... waiting.players = 다른 플레이어를 기다리는 중.. wave.enemies = [LIGHT_GRAY]{0} 마리 남았음 @@ -182,21 +182,36 @@ custom = 커스텀 builtin = 기본맵 map.delete.confirm = 이 맵을 삭제하시겠습니까? 이 명령은 취소할 수 없습니다! map.random = [accent]랜덤 맵 -map.nospawn = 이 맵에 플레이어가 스폰 할 코어가 없습니다! 맵 편집기에서 [royal]파란색[]코어를 맵에 추가하세요. -map.nospawn.pvp = 이 맵에는 적팀 코어가 없습니다! 에디터에서 [scarlet]빨간팀[] 코어를 추가하세요. +map.nospawn = 이 맵에 플레이어가 스폰 할 코어가 없습니다! 맵 편집기에서 [ROYAL]파란색[]코어를 맵에 추가하세요. +map.nospawn.pvp = 이 맵에는 적팀 코어가 없습니다! 에디터에서 [SCARLET]빨간팀[] 코어를 추가하세요. map.invalid = 파일이 잘못되었거나 손상되어 맵을 열 수 없습니다. editor.brush = 브러쉬 editor.openin = 편집기 열기 editor.oregen = 광물 무작위 생성 -editor.oregen.info = 광물 무작위 생성 : +editor.oregen.info = 광물 무작위 생성: editor.mapinfo = 맵 정보 -editor.author = 만든이 : -editor.description = 설명 : -editor.name = 이름 : +editor.author = 만든이: +editor.description = 설명: +editor.waves = Waves: +waves.title = Waves +waves.remove = Remove +waves.never = +waves.every = every +waves.waves = wave(s) +waves.perspawn = per spawn +waves.to = to +waves.boss = Boss +editor.default = [LIGHT_GRAY] +edit = Edit... +editor.name = 이름: editor.teams = 팀 editor.elevation = 지형 높이 -editor.errorimageload = [accent]{0}[] 파일을 불러오는데 오류가 발생했습니다. -editor.errorimagesave = [accent]{0}[] 파일 저장중 오류가 발생했습니다. +editor.errorload = Error loading file:\n[accent]{0} +editor.errorsave = Error saving file:\n[accent]{0} +editor.errorname = Map has no name defined. +editor.update = Update +editor.randomize = Randomize +editor.apply = Apply editor.generate = 생성 editor.resize = 맵 크기조정 editor.loadmap = 맵 불러오기 @@ -221,19 +236,34 @@ editor.loadimage = 지형 가져오기 editor.saveimage = 지형 내보내기 editor.unsaved = [scarlet]변경사항을 저장하지 않았습니다![]\n정말로 나가시겠습니까? editor.resizemap = 맵 크기 조정 -editor.mapname = 맵 이름 : +editor.mapname = 맵 이름: editor.overwrite = [accept]경고!이 명령은 기존 맵을 덮어씌우게 됩니다. editor.overwrite.confirm = [scarlet]경고![] 이 이름을 가진 맵이 이미 있습니다. 덮어 쓰시겠습니까? -editor.selectmap = 불러올 맵 선택 : -width = 넓이 : -height = 높이 : +editor.selectmap = 불러올 맵 선택: +filter.distort = Distort +filter.noise = Noise +filter.ore = Ore +filter.rivernoise = River Noise +filter.scatter = Scatter +filter.terrain = Terrain +filter.option.scale = Scale +filter.option.mag = Magnitude +filter.option.threshold = Threshold +filter.option.circle-scale = Circle Scale +filter.option.octaves = Octaves +filter.option.falloff = Falloff +filter.option.floor = Floor +filter.option.wall = Wall +filter.option.ore = Ore +width = 넓이: +height = 높이: menu = 메뉴 play = 플레이 load = 불러오기 save = 저장 fps = FPS: {0} tps = TPS: {0} -ping = 지연 시간: {0}ms +ping = Ping: {0}ms language.restart = 언어를 변경하려면 게임을 다시시작 해 주세요. settings = 설정 tutorial = 게임 방법 @@ -243,25 +273,25 @@ donate = 기부 abandon = 버리기 abandon.text = 이 구역과 모든 자원이 적에게 빼앗길 것입니다. locked = 잠김 -complete = [LIGHT_GRAY]완료 : -resume = 지역 계속 플레이 :\n[LIGHT_GRAY]{0} +complete = [LIGHT_GRAY]완료: +resume = 지역 계속 플레이:\n[LIGHT_GRAY]{0} bestwave = [LIGHT_GRAY]최고 점수: {0} launch = < 출격 > launch.title = 출격 성공 launch.next = [LIGHT_GRAY]다음 출격기회는 {0} 단계에서 나타납니다. -launch.unable = [scarlet]출격할 수 없습니다.[] 남은적 +launch.unable = [scarlet]출격할 수 없습니다.[] {0}마리 남음. launch.confirm = 출격하게 되면 모든 자원이 코어로 들어갑니다.\n또한 성공하기 전까지 기지로 돌아갈 수 없습니다. uncover = 털어넣기 configure = 로드아웃 설정 configure.locked = {0} 단계에서 로드아웃을 설정할 수 있음. zone.unlocked = [LIGHT_GRAY] 잠금 해제됨. zone.complete = 지역 조건이 충족됨. -zone.config.complete = Wave {0} reached:\nLoadout config unlocked. +zone.config.complete = 웨이브 {0} 달성:\n로드아웃 설정 잠금 해제됨. zone.resources = 자원 감지됨: -add = Add... -boss.health = Boss Health +add = 추가... +boss.health = 보스 체력 connectfail = [crimson]{0}[accent] 서버에 연결하지 못했습니다.[] -error.unreachable = 서버에 연결하지 못했습니다. +error.unreachable = 서버에 연결하지 못했습니다.\n서버 주소가 정확히 입력되었나요? error.invalidaddress = 잘못된 주소입니다. error.timedout = 시간 초과!\n서버에 포트 포워딩이 설정되어 있고 주소가 올바른지 확인하십시오. error.mismatch = 패킷 오류:\n클라이언트/서버 버전이 일치하지 않습니다.\n접속할려는 서버가 최신 버전의 Mindustry 인지 확인하세요! @@ -273,14 +303,9 @@ zone.groundZero.name = 그라운드 제로 zone.craters.name = 분화구 zone.frozenForest.name = 얼어붙은 숲 zone.ruinousShores.name = 파멸의 기슭 -zone.crags.name = Crags zone.stainedMountains.name = 얼룩진 산맥 -zone.impact0079.name = 충격 0079 zone.desolateRift.name = 황량한 강 -zone.arcticDesert.name = 북극 사막 -zone.dryWastes.name = 건조한 폐허 zone.nuclearComplex.name = 핵 생산 단지 -zone.moltenFault.name = 녹은 결점 settings.language = 언어 settings.reset = 설정 초기화 settings.rebind = 키 재설정 @@ -299,19 +324,21 @@ no = 아니오 info.title = [accent]정보 error.title = [crimson]오류가 발생했습니다. error.crashtitle = 오류가 발생했습니다. -blocks.outputspeed = Drill Speed: {0}/s +blocks.outputspeed = 채광 속도: {0}/s +blocks.efficiency = Efficiency: {0}% blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = 블록 정보 blocks.powerbalance = 전력: {0} blocks.poweroutput = 전력 출력: {0} -blocks.powercapacity = 최대 전력 용량 +blocks.powercapacity = 전력 용량 blocks.powershot = 1발당 전력 소모량 blocks.targetsair = 공중공격 가능 +blocks.items = Items: {0} blocks.itemsmoved = 이동 속도 blocks.shootrange = 사거리 blocks.size = 크기 -blocks.liquidcapacity = 최대 액체 용량 -blocks.maxitemssecond = 최대 아이템 보관량 +blocks.liquidcapacity = 액체 용량 +blocks.maxitemssecond = 아이템 보관량 blocks.powerrange = 전력 범위 blocks.poweruse = 전력 사용 blocks.powerdamage = 전력/데미지 @@ -328,22 +355,22 @@ blocks.inputitems = 사용되는 아이템들 blocks.outputitem = 출력 아이템 blocks.drilltier = 드릴 blocks.drillspeed = 기본 드릴 속도 -blocks.maxunits = Max Active Units +blocks.maxunits = 최대 활성유닛 blocks.liquidoutput = 액체 출력 blocks.liquidoutputspeed = 액체 출력속도 blocks.liquiduse = 액체 사용량 blocks.coolant = 냉각제 blocks.liquid = 액체 -blocks.coolantuse = 냉각수 사용 +blocks.coolantuse = 냉각제 사용 blocks.inputliquidfuel = 연료 액 blocks.liquidfueluse = 액체 연료 사용 blocks.boostitem = 가속 아이템 blocks.boostliquid = 가속 액체 blocks.health = 체력 -blocks.heat = Heat +blocks.heat = 발열 blocks.power = 전력 -blocks.progress = Build Progress -blocks.spawned = Units: {0}/{1} +blocks.progress = 건설 진행 +blocks.spawned = 유닛: {0}/{1} blocks.power.satisfaction = 전력 만족도 blocks.inaccuracy = 오차각 blocks.shots = 발포 횟수 @@ -369,6 +396,7 @@ category.items = 아이템 category.crafting = 제작 category.shooting = 사격 category.optional = 보조 아이템 +setting.animatedwater.name = 움직이는 물 setting.indicators.name = 인디게이터 표시 setting.autotarget.name = 자동 조준 setting.fpscap.name = 최대 FPS @@ -379,8 +407,8 @@ setting.difficulty.easy = 쉬움 setting.difficulty.normal = 보통 setting.difficulty.hard = 어려움 setting.difficulty.insane = 매우 어려움 -setting.difficulty.name = 난이도 : -setting.screenshake.name = 화면 흔들기 강도 +setting.difficulty.name = 난이도: +setting.screenshake.name = 화면 흔들기 setting.effects.name = 화면 효과 setting.sensitivity.name = 컨트롤러 감도 setting.saveinterval.name = 자동저장 간격 @@ -406,7 +434,7 @@ keybind.gridMode.name = 블록 선택 keybind.gridModeShift.name = 카테고리 선택 keybind.press = 키를 누르세요... keybind.press.axis = 축 또는 키를 누르세요... -keybind.screenshot.name = Map Screenshot +keybind.screenshot.name = 맵 스크린샷 keybind.move_x.name = 오른쪽/왼쪽 이동 keybind.move_y.name = 위 / 아래 중간 keybind.select.name = 선택 @@ -429,7 +457,7 @@ keybind.chat_history_next.name = 다음 채팅기록 keybind.chat_scroll.name = 채팅 스크롤 keybind.drop_unit.name = 유닛 드롭 keybind.zoom_minimap.name = 미니맵 확대 -mode.help.title = 도움말 +mode.help.title = 모드 도움말 mode.survival.name = 생존 mode.survival.description = 이것은 일반 모드입니다. 제한된 자원을 가지고 자동으로 다음 단계가 시작됩니다. mode.sandbox.name = 샌드박스 @@ -437,7 +465,7 @@ mode.sandbox.description = 무한한 자원을 가지고 자유롭게 다음 단 mode.freebuild.name = 자유 건축 mode.freebuild.description = 제한된 자원을 가지고 다음 단계를 시작할 수 있습니다. mode.pvp.name = PvP -mode.pvp.description = 몹이 아닌 실제 플레이어와 PvP를 합니다. +mode.pvp.description = 실제 플레이어와 PvP를 합니다. mode.attack.name = 공격 mode.attack.description = 일정 시간마다 적이 오는 단계가 없으며, 적의 기지를 파괴하는 것을 목표로 합니다. content.item.name = 아이템 @@ -450,28 +478,28 @@ item.copper.description = 모든 종류의 블록에서 광범위하게 사용 item.lead.name = 납 item.lead.description = 쉽게 구할 수 있으며, 전자 및 액체 수송 블록에서 광범위하게 사용되는 자원입니다. item.coal.name = 석탄 -item.coal.description = 쉽게 구할 수 있으며, 주로 제련소 등에서 연료로 사용됩니다. +item.coal.description = 흔하고 쉽게 구할 수 있는 연료. item.graphite.name = 흑연 item.titanium.name = 티타늄 item.titanium.description = 파이프 재료나 고급 드릴, 비행기/기체 등에서 재료로 사용되는 자원입니다. item.thorium.name = 토륨 -item.thorium.description = 건물의 재료, 포탑의 탄약 또는 핵연료로 사용되는 방사성 금속입니다. +item.thorium.description = 건물의 재료, 터렛의 탄약 또는 핵연료로 사용되는 방사성 금속입니다. item.silicon.name = 실리콘 item.silicon.description = 매우 유용한 반도체로, 기체를 만들거나 태양 전지판 등 전자 건물에 사용할 수 있습니다. item.plastanium.name = 플라스터늄 item.plastanium.description = 고급 항공기 및 분열 탄약에 사용되는 가벼운 연성 재료. -item.phase-fabric.name = 메타 +item.phase-fabric.name = 위상 패브릭 item.phase-fabric.description = 최첨단 전자 제품과 자기수리 기술에 사용되는 거의 무중력에 가까운 물질입니다. -item.surge-alloy.name = 설금 +item.surge-alloy.name = 서지 합금 item.surge-alloy.description = 독특한 전기 특성을 가진 고급 합금입니다. -item.spore-pod.name = Spore Pod -item.spore-pod.description = Used for conversion into oil, explosives and fuel. +item.spore-pod.name = 포자 포드 +item.spore-pod.description = 석유, 폭발물 및 연료로 전환하는데 사용됩니다. item.sand.name = 모래 item.sand.description = 고밀도 합금 제작이나 제련시 이 광물을 사용하여 소모 재료를 줄이는 등 광범위하게 사용되는 일반적인 재료입니다. -item.blast-compound.name = 폭발물 -item.blast-compound.description = 포탑 및 건설의 재료로 사용되는 휘발성 폭발물.\n연료로도 사용할 수 있지만, 별로 추천하지는 않습니다. -item.pyratite.name = 피라테 -item.pyratite.description = 폭발성을 가진 재료로, 주로 포탑의 탄약으로 사용됩니다. +item.blast-compound.name = 폭발 화합물 +item.blast-compound.description = 터렛 및 건설의 재료로 사용되는 휘발성 폭발물.\n연료로도 사용할 수 있지만, 별로 추천하지는 않습니다. +item.pyratite.name = 피라타이트 +item.pyratite.description = 폭발성을 가진 재료로, 주로 터렛의 탄약으로 사용됩니다. item.metaglass.name = 메타유리 item.metaglass.description = 초강력 유리 화합물. 액체 분배 및 저장에 광범위하게 사용됩니다. item.scrap.name = 조각 @@ -479,7 +507,7 @@ item.scrap.description = 오래된 건물과 유닛의 남은 잔해. 미량의 liquid.water.name = 물 liquid.slag.name = 광재 liquid.oil.name = 석유 -liquid.cryofluid.name = 냉각수 +liquid.cryofluid.name = 냉각유체 mech.alpha-mech.name = 알파 mech.alpha-mech.weapon = 중무장 소총 mech.alpha-mech.ability = 드론 소환 @@ -520,9 +548,18 @@ mech.itemcapacity = [LIGHT_GRAY]아이템 수용 용량: {0} mech.minespeed = [LIGHT_GRAY]채광 속도: {0} mech.minepower = [LIGHT_GRAY]채광 레벨: {0} mech.ability = [LIGHT_GRAY]능력: {0} -liquid.heatcapacity = [LIGHT_GRAY]발열량: {0} +liquid.heatcapacity = [LIGHT_GRAY]발열 용량: {0} liquid.viscosity = [LIGHT_GRAY]점도: {0} liquid.temperature = [LIGHT_GRAY]온도: {0} +block.grass.name = Grass +block.salt.name = Salt +block.sandrocks.name = Sand Rocks +block.spore-pine.name = Spore Pine +block.shale.name = Shale +block.shale-boulder.name = Shale Boulder +block.moss.name = Moss +block.spore-moss.name = Spore Moss +block.shalerocks.name = Shale Rocks block.scrap-wall.name = 조각벽 block.scrap-wall-large.name = 큰 조각벽 block.scrap-wall-huge.name = 거대한 조각 벽 @@ -557,33 +594,27 @@ block.pine.name = 소나무 block.white-tree-dead.name = 죽은 하얀나무 block.white-tree.name = 하얀 나무 block.spore-cluster.name = 포자낭 -block.stained-rocks.name = 얼룩진 바위 -block.stained-stone.name = 얼룩진 돌 -block.stained-rocks-red.name = 얼룩진 빨간 바위 -block.stained-stone-red.name = 얼룩진 빨간 돌 -block.stained-rocks-yellow.name = 얼룩진 노란 바위 -block.stained-stone-yellow.name = 얼룩진 노란 돌 -block.stained-boulder.name = 얼룩진 둥근 돌 block.metal-floor.name = 메탈 바닥 block.metal-floor-2.name = 메탈 바닥 2 block.metal-floor-3.name = 메탈 바닥 3 block.metal-floor-5.name = 메탈 바닥 5 block.metal-floor-damaged.name = 손상된 메탈 바닥 -block.ignarock.name = 얼은바위 -block.hotrock.name = 뜨거운바위 +block.ignarock.name = 얼은 바위 +block.hotrock.name = 뜨거운 바위 block.magmarock.name = 마그마 바위 block.cliffs.name = 절벽 block.copper-wall.name = 구리벽 block.copper-wall-large.name = 큰 구리벽 block.titanium-wall.name = 티타늄 벽 block.titanium-wall-large.name = 대형 티타늄 벽 -block.phase-wall.name = 메타벽 -block.phase-wall-large.name = 큰 메타벽 +block.phase-wall.name = 상직물벽 +block.phase-wall-large.name = 큰 상직물벽 block.thorium-wall.name = 토륨벽 block.thorium-wall-large.name = 대형 토륨벽 block.door.name = 문 block.door-large.name = 대형문 block.duo.name = 듀오 +block.scatter.name = Scatter block.hail.name = 헤일 block.lancer.name = 랜서 block.conveyor.name = 컨베이어 @@ -596,16 +627,16 @@ block.sorter.description = 아이템을 넣어서 필터에 설정된 아이템 block.overflow-gate.name = 오버플로 게이트 block.overflow-gate.description = 정면으로 가는 자원이 막히면 옆으로 출력하고, 그렇지 않으면 계속 정면으로 출력합니다. block.silicon-smelter.name = 실리콘 제련소 -block.phase-weaver.name = 메타 합성기 +block.phase-weaver.name = 상직물 합성기 block.pulverizer.name = 분쇄기 block.cryofluidmixer.name = 냉각수 제조기 block.melter.name = 융해기 block.incinerator.name = 소각로 -block.spore-press.name = Spore Press +block.spore-press.name = 포자 압축기 block.separator.name = 셉터 -block.power-node.name = 전력 송신기 -block.power-node-large.name = 대형 전력 송신기 -block.surge-tower.name = 설금 타워 +block.power-node.name = 전력 노드 +block.power-node-large.name = 대형 전력 노드 +block.surge-tower.name = 서지 합금 타워 block.battery.name = 배터리 block.battery-large.name = 대형 배터리 block.combustion-generator.name = 화력 발전기 @@ -637,11 +668,11 @@ block.wave.name = 파도 block.swarmer.name = 스웜 block.salvo.name = 살보 block.ripple.name = 립플 -block.phase-conveyor.name = 메타 컨베이어 -block.bridge-conveyor.name = 터널 +block.phase-conveyor.name = 위상 컨베이어 +block.bridge-conveyor.name = 터널 컨베이어 block.plastanium-compressor.name = 플라스터늄 압축기 -block.pyratite-mixer.name = 피라테 제조기 -block.blast-mixer.name = 폭발물 제조기 +block.pyratite-mixer.name = 피라타이트 혼합기 +block.blast-mixer.name = 폭발물 혼합기 block.solar-panel.name = 태양 전지판 block.solar-panel-large.name = 대형 태양 전지판 block.oil-extractor.name = 석유 추출기 @@ -650,38 +681,39 @@ block.phantom-factory.name = 팬텀 드론 공장 block.wraith-factory.name = 유령 전투기 공장 block.ghoul-factory.name = 구울 폭격기 공장 block.dagger-factory.name = 디거 기체 공장 +block.crawler-factory.name = Crawler Mech Factory block.titan-factory.name = 타이탄 기체 공장 block.fortress-factory.name = 포트리스 기체 공장 block.revenant-factory.name = 레비던트 전투기 공장 -block.repair-point.name = 정비소 +block.repair-point.name = 수리 지점 block.pulse-conduit.name = 퓨즈 파이프 -block.phase-conduit.name = 메타 파이프 +block.phase-conduit.name = 상직물 파이프 block.liquid-router.name = 액체 분배기 block.liquid-tank.name = 물탱크 block.liquid-junction.name = 액체 교차기 block.bridge-conduit.name = 다리 파이프 block.rotary-pump.name = 동력 펌프 block.thorium-reactor.name = 토륨 원자로 -block.mass-driver.name = 자원 발사기 -block.blast-drill.name = 고속 드릴 +block.mass-driver.name = 매스 드라이버 +block.blast-drill.name = 압축 공기분사 드릴 block.thermal-pump.name = 화력 펌프 block.thermal-generator.name = 열발전기 -block.alloy-smelter.name = 설금 제련소 +block.alloy-smelter.name = 서지 합금 제련소 block.mend-projector.name = 수리 프로젝터 -block.surge-wall.name = 설금벽 -block.surge-wall-large.name = 큰 설금벽 +block.surge-wall.name = 서지 합금벽 +block.surge-wall-large.name = 큰 서지 합금벽 block.cyclone.name = 사이클론 block.fuse.name = 퓨즈 block.shock-mine.name = 전격 지뢰 block.overdrive-projector.name = 오버드라이브 프로젝터 block.force-projector.name = 보호막 프로젝터 block.arc.name = 아크 -block.rtg-generator.name = 토륨 발전소 +block.rtg-generator.name = RTG 발전기 block.spectre.name = 스펙터 block.meltdown.name = 멜트다운 block.container.name = 컨테이너 block.launch-pad.name = 발사대 -block.launch-pad.description = Launches batches of items without any need for a core launch. Unfinished. +block.launch-pad.description = 출격할 필요 없이 아이템을 수송시킵시다. 미완성. team.blue.name = 블루팀 team.red.name = 레드팀 team.orange.name = 오렌지팀 @@ -705,8 +737,8 @@ unit.fortress.name = 포트리스 unit.fortress.description = 중포 지상 유닛.\n높은 공격력을 가진 총과 높은 체력을 가지고 있습니다. unit.revenant.name = 레비던트 unit.eruptor.name = 이어럽터 -unit.chaos-array.name = 혼돈 배열 -unit.eradicator.name = 에라데이터 +unit.chaos-array.name = 카오스 배열 +unit.eradicator.name = 박멸 unit.lich.name = 리치 unit.reaper.name = 사신 tutorial.begin = 플레이어의 주요 목표는 [LIGHT_GRAY]적군[]을 제거하는 것입니다.\n\n이 게임은 [accent]구리를 채광[]하는 것으로 시작합니다.\n이것을 하기 위해 플레이어의 중심부 근처에 있는 구리 광맥을 누르세요. @@ -723,110 +755,111 @@ tutorial.siliconsmelter = 이제 이코어는 채굴과 수리하기 위한[acce tutorial.silicondrill = 실리콘을 제작하려면[accent] 석탄[] 과[accent] 모래[]가 필요합니다.\n드릴을 먼저 건설해보는건 어떤가요? tutorial.generator = 이 건물은 [LIGHT_YELLOW]전력[]이 필요합니다.\n[accent] 석탄 발전기[]를 건설하세요. tutorial.generatordrill = [accent] 석탄 발전기[]는 연료가 필요합니다.\n[accent] 석탄[]을 드릴로 채굴해서 연료를 체워주세요. -tutorial.node = 전력은 송신해줄 송신기가 필요합니다.\n[accent] 전력 송신기[]를 석탄 등등 발전기 옆에 설치해서 생산된 전기를 다른곳으로 송신합시다. -tutorial.nodelink = 전력은 전력 블록과 발전기에 연결하거나, 연결된 전력 송신기를 통해 전송이 가능합니다. \n\n전력 송신기를 누르고 발전기와 실리콘 제련기를 선택하여 전원을 연결합시다. +tutorial.node = 전력은 송신해줄 노드가 필요합니다.\n[accent] 전력 노드[]를 석탄 등등 발전기 옆에 설치해서 생산된 전기를 다른곳으로 송신합시다. +tutorial.nodelink = 전력은 전력 블록과 발전기에 연결하거나, 연결된 전력 노드를 통해 전송이 가능합니다. \n\n전력 노드를 누르고 발전기와 실리콘 제련기를 선택하여 전원을 연결합시다. tutorial.silicon = 실리콘이 생산되고 있습니다.\n\n생산 시스템의 개선을 권고 드립니다. tutorial.daggerfactory = 이[accent] 디거 기체 공장[]은\n\n공격하는 기체를 생산하기 위해 사용됩니다. tutorial.router = 공장을 작동시키기 위해 자원이 필요합니다.\n컨베이어에 운반되고 있는 자원을 분할할 분배기를 만드세요. tutorial.dagger = 전력 노드를 공장에 연결하세요.\n일단 요구 사항이 충족되면 기체 생산을 시작합니다.\n\n필요에 따라 드릴 및 발전기, 컨베이어를 더 많이 만들 수 있습니다. tutorial.battle = [LIGHT_GRAY]적[]의 코어가 드러났습니다.\n당신의 부대와 디거를 사용하여 파괴하세요. -block.copper-wall.description = 구리로 만든 방어벽.\n가장 약한 방어벽입니다. -block.copper-wall-large.description = 구리로 만든 큰 방어벽.\n일반 구리벽의 4개를 합쳐놓은 벽이며, 가장 약한 방어벽입니다. -block.thorium-wall.description = 토륨으로 만든 방어벽.\n아무 기능이 없는 튼튼한 방어벽입니다. -block.thorium-wall-large.description = 토륨으로 만든 큰 방어벽.\n토륨벽을 4개 합쳐놓은 벽이며, 내구성이 뛰어납니다. -block.phase-wall.description = 메타로 제작하는 방어벽.날라오는 모든 총알을 튕겨내고 데미지를 입는 특수한 벽입니다. -block.phase-wall-large.description = 메타로 제작한 큰 방어벽.\n날라오는 총알을 모두 튕겨냅니다. -block.surge-wall.description = 데미지를 입으면 번개를 일으켜 대상에게 피해를 입히는 특수한 벽입니다. -block.surge-wall-large.description = 설금을 재료로 한 큰 방어벽.\n데미지를 입으면 번개를 일으켜 대상에게 피해를 입힙니다. -block.door.description = 유닛이 지나갈 수 있도록 만든 문.\n클릭하면 열고 닫습니다. -block.door-large.description = 유닛이 자나갈 수 있도록 만든 큰 문.\n클릭하면 열고 닫습니다. -block.mend-projector.description = 주위 건물을 넓은 범위로 치료하는 건물입니다. -block.overdrive-projector.description = 범위 내 모든 행동의 속도를 2배 높여주는 보조형 건물입니다. -block.force-projector.description = 보호막을 생성하는 건물.\n기본적으로 전력만 있으면 작동하지만, 메타를 넣어 보호막의 범위를 크게 확장시킬 수 있습니다. -block.shock-mine.description = 적이 이 블록을 지나가면 전격 공격을 하는 함정형 방어 건물입니다. -block.duo.description = 범용성을 가진 터렛.\n지상 및 공중공격을 하며, 초반에 유용합니다. -block.arc.description = 목표 방향으로 전격 공격을 하는 포탑입니다. -block.hail.description = 장거리 지상 공격을 하는 터렛입니다.\n적이 공격하기 전에 쓸어버릴 수 있습니다. -block.lancer.description = 중거리 레이져 포탑입니다.\n적을 관통하기 때문에 뭉쳐있는 적들에게 매우 효과적입니다. -block.wave.description = 적이 있는 자리에 액체를 뿌립니다.\n이 포탑을 활용하여 액체를 뿌린 곳에 불을 붙이거나 적을 느리게 할 수 있습니다. -block.salvo.description = 명중률이 높고, 3발씩 끊어 발사하는 포탑입니다. -block.swarmer.description = 4발씩 끊어서 유도체를 발사하는 포탑입니다 -block.ripple.description = 4개의 탄약으로 나눠 발사하여 명중률이 낮지만, 사거리가 매우 긴 포탑입니다. -block.cyclone.description = 낮은 명중률과 높은 RPM 을 가진 포탑입니다.\n사격하는데 쿨타임이 거의 없습니다. -block.fuse.description = 단거리에서 범위형 레이저를 발사하는 포탑입니다. -block.spectre.description = 높은 명중률과 RPM 을 가진 포탑입니다.\n탄약이 남아있는 한 멈추지 않고 계속 연사합니다. -block.meltdown.description = 목표를 따라 초대형 레이져를 발사하는 포탑입니다.\n조준 시간이 길어 공중에는 적합하지 않지만 뭉쳐있는 몹에게 매우 효과가 좋습니다. -block.conveyor.description = 느린 속도로 자원을 수송할 수 있는 컨베이어. -block.titanium-conveyor.description = 빠른 속도로 자원을 수송할 수 있는 컨베이어. -block.phase-conveyor.description = 자원을 지정된 방향으로 바로 이동시켜 주는 컨베이어 입니다. -block.junction.description = 컨베이어를 교차시켜 자원을 수송할 때 사용할 수 있는 블록입니다. -block.mass-driver.description = 자원을 받아서 다른 물질 이동기로 전달할 수 있는 블록입니다.\n엄청난 사거리를 가지고 있으며, 주로 컨베이어가 접근할 수 없는 곳에 유용하게 사용됩니다. -block.silicon-smelter.description = 실리콘을 제작하는 것은 어렵습니다. -block.plastanium-compressor.description = 플라스터늄을 제조할 수 있는 건물입니다. -block.phase-weaver.description = 메타를 제작할 수 있는 건물입니다. -block.alloy-smelter.description = 설금을 제작할 수 있는 건물입니다. -block.pulverizer.description = 돌을 갈아서 모래로 만들 수 있는 건물입니다. -block.pyratite-mixer.description = 피라테를 제조할 수 있는 건물입니다. -block.blast-mixer.description = 폭발물을 제조할 수 있는 건물입니다. -block.cryofluidmixer.description = 냉각수를 제작할 수 있는 건물입니다. -block.melter.description = 돌로 용암을 만들 수 있는 건물입니다. +block.copper-wall.description = 싸구려 방어블록.\n처음에 몇번 웨이브에서 건물과 터렛을 보호하는 데 유용함. +block.copper-wall-large.description = 싸구려 방어블록.\n처음에 몇번 웨이브에서 건물과 터렛을 보호하는 데 유용함.\n4개를 합친 블록입니다. +block.thorium-wall.description = 강력한 방어블록.\n적 공격으로부터 좋은 보호를 할 수 있습니다. +block.thorium-wall-large.description = 강력한 방어블록.\n적 공격으로부터 좋은 보호를 할 수 있습니다.\n4개를 합친 블록입니다. +block.phase-wall.description = 토륨 벽만큼 강하지 않지만 벽을 향해 날아오는 총알이 너무 강력하지 않으면 총알을 튕겨냅니다. +block.phase-wall-large.description = 토륨 벽만큼 강하지 않지만 벽을 향해 날아오는 총알이 너무 강력하지 않으면 총알을 튕겨냅니다.\n4개를 합친 블록입니다. +block.surge-wall.description = 최강 방어블록.\n공격을 받으면 낮은 확률로 공격자에게 전격 공격을 합니다. +block.surge-wall-large.description = 최강 방어블록.\n공격을 받으면 낮은 확률로 공격자에게 전격 공격을 합니다.\n4개를 합친 블록입니다. +block.door.description = 눌러서 열고 닫을 수 있는 작은 문.\n만약 문이 열리면, 적들은 총을 쏘며 문을 통과할 수 있습니다. +block.door-large.description = 누르는 것으로 여닫을 수 있는 큰 문.\n만약 문이 열리면, 적들은 총을 쏘며 문을 통과할 수 있습니다.\n4개를 합친 블록입니다. +block.mend-projector.description = 주변 건물을 주기적으로 치료합니다. +block.overdrive-projector.description = 드릴과 컨베이어와 같은 인근 건물의 속도를 높여줍니다. +block.force-projector.description = 총알에게서 내부의 건물과 유닛을 보호하면서 그 주위에 육각형 보호막을 만듭니다. +block.shock-mine.description = 지뢰를 밟는 적에게 피해를 줍니다. 적에게는 거의 보이지 않습니다. +block.duo.description = 작고 싼 터렛. +block.scatter.description = A medium-sized anti-air turret. Sprays clumps of lead or scrap flak at enemy units. +block.arc.description = 적을 향해 무작위 각도로 전기를 쏘는 작은 터렛. +block.hail.description = 작은 포병 터렛. +block.lancer.description = 충전된 전기빔을 쏘는 중형 터렛. +block.wave.description = 액체를 뿜는 중간 크기의 속화 터렛. +block.salvo.description = 살보에서 사격을 하는 중형 터렛. +block.swarmer.description = 유도 미사일을 발사하는 중형 터렛. +block.ripple.description = 여러 발의 사격을 동시에 하는 대형 포대. +block.cyclone.description = 대형 초고속 사격 터렛. +block.fuse.description = 강력한 단거리 빔을 쏘는 대형 터렛. +block.spectre.description = 한 번에 두 발의 강력한 총알을 쏘는 대형 터렛. +block.meltdown.description = 강력한 장거리 빔을 쏘는 대형 터렛. +block.conveyor.description = 기본 아이템 수송 블록. 아이템을 앞으로 이동시켜 자동으로 터렛이나 건물에 넣어줍니다. 회전식. +block.titanium-conveyor.description = 고급 아이템 운송 블록. 표준 컨베이어보다 아이템을 더 빨리 이동시킨다. +block.phase-conveyor.description = 고급품 수송 블록. 여러 타일을 통해 아이템을 연결된 위상 컨베이어로 텔레포트하기 위해 전력을 사용합니다. +block.junction.description = 2개의 컨베이어 벨트를 교차시키는 다리 역할을 합니다. 서로 다른 재료를 다른 장소로 운반하는 두 개의 다른 컨베이어의 상황에서 유용합니다. +block.mass-driver.description = 최강 아이템 수송 블록. 몇 가지 아이템을 모아 장거리에서 또 다른 매스 드라이버에게 발사합니다. +block.silicon-smelter.description = 고순도 석탄으로 모래를 줄여 실리콘을 생산합니다. +block.plastanium-compressor.description = 석유와 티타늄으로 플라스타늄을 생산합니다. +block.phase-weaver.description = 방사능 토륨과 많은 량의 모래에서 상직물을 생산합니다. +block.alloy-smelter.description = 티타늄, 납, 실리콘, 구리로부터 서지 합금을 생산합니다. +block.pulverizer.description = 모래로 돌을 부숩니다. 천연 모래가 부족할 때 유용합니다. +block.pyratite-mixer.description = 석탄, 납, 모래를 가연성이 높은 피라타이트로 만듭니다. +block.blast-mixer.description = 기름을 사용하여 피라타이트를 인화성은 떨어지지만 폭발성은 높은 폭발성 화합물로 변환시킵니다. +block.cryofluidmixer.description = 물과 티타늄을 냉각에 훨씬 더 효과적인 냉동액으로 결합시킵니다. +block.melter.description = 고철을 녹여 더 많은 처리나 터렛의 사용을 위해 광재에 녹입니다. block.incinerator.description = 불필요한 아이템을 소각시켜 줄 수 있는 건물입니다. -block.spore-press.description = Compresses spore pods into oil. +block.spore-press.description = 포자 포드를 석유로 바꿔줍니다. block.separator.description = 돌을 분해하여 각종 자원으로 재활용 할 수 있게 해 주는 건물입니다. -block.power-node.description = 생성된 전력를 다른 건물로 전달하기 위한 전력 노드입니다. +block.power-node.description = 전원을 연결된 노드로 전송합니다. 최대 4개의 동력원, 싱크 또는 노드를 연결할 수 있습니다. 노드는 인접한 블록으로부터 전원을 공급하거나 공급받을 수 있습니다. block.power-node-large.description = 생성된 전력를 다른 건물로 전달하기 위한 건물이며, 일반 노드보다 더 많은 전력을 이동시킬 수 있습니다. -block.battery.description = 흔히 아는 충전식 배터리입니다.\n전력을 사용하는 건물에 전력이 떨어질경우, 이 배터리를 전력 노드에 연결하면 이 배터리에 저장된 전력을 소모하여 지속적으로 공급할 수 있습니다. -block.battery-large.description = 일반 배터리보다 용량이 매우 커진 커진 배터리. -block.combustion-generator.description = 석탄을 연료로 전력를 생산해내는 발전소 입니다. -block.turbine-generator.description = 석탄 발전기보다 더 많은량의 전력를 생산하는 발전기입니다. -block.thermal-generator.description = 용암을 원료로 전력을 생산할 수 있는 발전소입니다. -block.solar-panel.description = 태양열을 받아 자기 스스로 전력을 생산하는 건물입니다. -block.solar-panel-large.description = 태양열을 받아 자기 스스로 전력을 생산하지만, 이 블록은 더 빨리 전력을 생산할 수 있습니다. -block.thorium-reactor.description = 토륨을 원료로 하는 토륨 원자로 입니다.\n많은 전력을 생산하지만 엄청난 열을 발생시키기 때문에, 많은 량의 물 또는 냉각수가 있어야 터지지 않고 작동합니다. -block.rtg-generator.description = 냉각은 필요 없지만 토륨 원자로보다 적은량의 전력을 생산하는 방사선 동위원소 열전자 발전기. -block.unloader.description = 해당 창고 및 코어에서 자원을 빼내는데 사용됩니다. -block.container.description = 아이템을 저장할 수 있는 소형 창고입니다. -block.vault.description = 아이템을 저장할 수 있는 대형 창고입니다. -block.mechanical-drill.description = 구리로 제작할 수 있는 기본 드릴입니다. -block.pneumatic-drill.description = 돌, 티타늄을 채광할 수 있는 고급 드릴입니다. -block.laser-drill.description = 토륨을 채광할 수 있는 최고급 드릴입니다.\n전력과 물을 공급하여 빠른 속도로 채광할 수 있습니다. -block.blast-drill.description = 최상위 드릴입니다.\n엄청난 양의 전력과 물을 소모하는 대신, 매우 빠른 속도로 채광합니다. -block.water-extractor.description = 바닥에서 물을 추출하여 건물에 공급할 수 있는 건물입니다. -block.cultivator.description = 잔디에서 바이오메터를 추출할 수 있는 건물입니다. -block.oil-extractor.description = 석유를 추출 해 주는 건물입니다. -block.trident-ship-pad.description = 대형 폭격기 역할을 하는 삼지창 비행선으로 바꿀 수 있는 패드입니다.\n\n누르거나 클릭하여 이 기체로 바꿉니다. -block.javelin-ship-pad.description = 처음에는 느리지만 가속도가 붙어 다른 비행선보다 5배 이상 빠르게 움직일 수 있으며, 적에게 부딛쳐서 공격할 수 있는 자비린 패드입니다.\n\n누르거나 클릭하여 이 기체로 바꿉니다. -block.glaive-ship-pad.description = 글레브 비행선으로 바꿀 수 있는 패드입니다.\n\n누르거나 클릭하여 이 기체로 바꿉니다. -block.tau-mech-pad.description = 주위 건물이나 기체를 치료하는 타우 기체로 바꿀 수 있는 패드입니다.\n\n누르거나 클릭하여 이 기체로 바꿉니다. -block.delta-mech-pad.description = 전방에 전격 공격을 하는 델타 기체로 바꿀 수 있는 패드입니다.\n\n누르거나 클릭하여 이 기체로 바꿉니다. -block.omega-mech-pad.description = 건물 파괴용 기체의 끝판왕이며, 공격시 방어모드로 전환되어 최대 90% 피해를 줄일 수 있는 오메가 기체로 바꿀 수 있는 패드입니다.\n\n누르거나 클릭하여 이 기체로 바꿉니다. -block.spirit-factory.description = 코어에 기본적으로 스폰되는 드론인 스피릿 유닛을 생산하는 공장입니다. -block.phantom-factory.description = 일반 드론보다 좀 더 효율적이며 빠른 새 드론인 팬텀을 생산하는 공장입니다. -block.wraith-factory.description = 지상 및 공중을 공격할 수 있으며, 공격후 빠지고 다시 공격하는 방식을 사용하는 유령 전투기를 소환하는 공장입니다. -block.ghoul-factory.description = 지상만 공격할 수 있으며, 건물을 집중 폭격하는데 목적이 있는 구울 비행선 유닛을 생산하는 공장입니다. -block.dagger-factory.description = 지상 및 공중을 공격할 수 있으며, 플레이어 기본 기체인 디거를 생산하는 공장입니다. -block.titan-factory.description = 지상 및 공중을 공격할 수 있으며, 총알 대신 근접 화염 방사기를 가진 타이탄 유닛을 생산할 수 있는 공장입니다. -block.fortress-factory.description = 지상 유닛의 최종판이며, 강력한 총을 가진 포트리스를 생산하는 공장입니다. -block.revenant-factory.description = 공중 유닛의 최종판이며, 강력한 레이저 총을 가진 레비던트 유닛을 생산할 수 있는 공장입니다. -block.repair-point.description = 근처 유닛들을 수리하는 건물입니다.\n커맨드 센터에서 후퇴 명령시 공중 유닛이 이 건물로 이동하여 수리를 받습니다. +block.battery.description = 전력 생산량에 여유가 있을경우, 생산된 잉여 전력을 여기에 저장합니다. +block.battery-large.description = 일반 배터리보다 훨씬 많은 량의 전력을 저장합니다. +block.combustion-generator.description = 기름이나 인화성 물질을 태워 전력을 발생시킵니다. +block.turbine-generator.description = 연소 발생기보다 효율적이지만, 추가 액체가 필요합니다. +block.thermal-generator.description = 뜨거운 위치에 건설하면 전력을 생산합니다. +block.solar-panel.description = 태양으로부터 소량의 전력을 공급합니다. +block.solar-panel-large.description = 일반 태양 전지판보다 훨씬 나은 전력을 공급하지만, 건축비도 훨씬 비쌉니다. +block.thorium-reactor.description = 고방사능 토륨으로부터 막대한 양의 전력을 발생시킵니다. 지속적인 냉각이 필요하며 냉각제의 양이 부족하면 크게 폭발합니다. 전력 출력은 최대 용량에서 기본 전력을 발생시키는 완전성에 따라 결정됩니다. +block.rtg-generator.description = 냉각은 필요 없지만 토륨 원자로에 비해 전력을 적게 공급하는 방사성 동위원소 열전 발생기. +block.unloader.description = 컨테이너, 금고 또는 코어에서 인접한 블록으로 아이템을 출하합니다. 출하시킬 아이템의 종류는 언로더를 눌러 지정할 수 있습니다. +block.container.description = 각종 소량의 자원을 저장할 수 있습니다.[LIGHT_GRAY언로더[]를 사용하여 컨테이너에서 물건을 회수할 수 있습니다. +block.vault.description = 각종 대량의 자원을 저장할 수 있습니다.[LIGHT_GRAY]언로더[]를 사용하여 금고에서 물건을 회수할 수 있습니다. +block.mechanical-drill.description = 싸구려 드릴. 적절한 타일 위에 놓였을때 매우 느린 속도로 계속 출력합니다. +block.pneumatic-drill.description = 기압을 이용하여 보다 빠르고 단단한 물질을 채광할 수 있는 향상된 드릴. +block.laser-drill.description = 토륨을 채광할 수 있는 최고급 드릴입니다. 전력과 물을 공급하여 빠른 속도로 채광할 수 있습니다. +block.blast-drill.description = 최상위 드릴입니다. 많은량의 전력이 필요합니다. +block.water-extractor.description = 땅에서 물을 추출합니다. 근처에 호수가 없을 때 사용하세요. +block.cultivator.description = 소량의 포자를 산업용으로 준비된 포자로 배양하는 건물입니다. +block.oil-extractor.description = 모래에서 기름을 추출하기 위해 대량을 전력을 사용합니다. 근처에 직접적인 석유 공급원이 없을때 사용하세요. +block.trident-ship-pad.description = 지금 타고있는 배를 떠나 잘 무장된 중폭격기로 갈아타세요.\n누르거나 클릭하여 이 기체로 바꿉니다. +block.javelin-ship-pad.description = 지금 타고있는 배를 떠나 전격 무기와 강력하고 빠른 요격체로 변신합니다.\n누르거나 클릭하여 이 기체로 바꿉니다. +block.glaive-ship-pad.description = 지금 타고있는 배를 떠나 크고 잘 무장된 기체로 갈아타세요.\n누르거나 클릭하여 이 기체로 바꿉니다. +block.tau-mech-pad.description = 지금 타고있는 배를 떠나 아군 건물이나 유닛을 치료할 수 있는 지원형 기체로 갈아타세요.\n누르거나 클릭하여 이 기체로 바꿉니다. +block.delta-mech-pad.description = 지금 타고있는 배를 떠나 뺑소니 공격을 위해 만들어진 빠르고 가벼운 기체로 갈아타세요.\n누르거나 클릭하여 이 기체로 바꿉니다. +block.omega-mech-pad.description = 지금 타고있는 배를 떠나 최전방 공격을 위해 만든 부피가 크고 잘 무장된 기체로 갈아타세요.\n누르거나 클릭하여 이 기체로 바꿉니다. +block.spirit-factory.description = 광석을 채굴하고 블록을 수리하는 경량 드론을 생산합니다. +block.phantom-factory.description = 스피릿 드론보다 훨씬 효과적인 첨단 드론 유닛을 생산합니다. +block.wraith-factory.description = 빠른 뺑소니 요격기 유닛을 생산합니다. +block.ghoul-factory.description = 중탄두 폭격기를 생산합니다. +block.dagger-factory.description = 기본 지상 유닛을 생산합니다. +block.titan-factory.description = 첨단 장갑 지상부대를 생산합니다. +block.fortress-factory.description = 중대포 지상부대를 생산합니다. +block.revenant-factory.description = 중량의 레이저 포대를 가진 공중부대를 생산합니다. +block.repair-point.description = 주변에서 가장 가까운 손상된 유닛을 지속적으로 치료합니다. block.conduit.description = 일반 파이프.\n액체가 지나갈 수 있도록 해 줍니다. -block.pulse-conduit.description = 티타늄으로 만들어 졌으며, 일반 파이프보다 액체 수용량이 높습니다. -block.phase-conduit.description = 물을 먼거리로 순간이동 시켜 주는 장치입니다. +block.pulse-conduit.description = 고급 액체 수송블록. 일반 파이프보다 액체 운송 속도가 빠릅니다. +block.phase-conduit.description = 고급 액체 수송블록. 물을 먼거리로 순간이동 시켜 주는 장치입니다. block.liquid-router.description = 물펌프를 다른 방향으로 분배할 수 있게 하는 블럭입니다. block.liquid-tank.description = 액체 종류를 저장할 수 있는 물탱크 입니다. block.liquid-junction.description = 물펌프와 다른 물펌프를 서로 교차시키게 할 수 있는 블럭입니다. block.bridge-conduit.description = 다리와 다리 사이를 연결하여 액체가 지나갈 수 있게 해 줍니다.\n주로 다리 사이에 지나갈 수 없는 장애물이 있을 때 사용합니다. -block.mechanical-pump.description = 구리로 제작할 수 있는 기계식 물펌프입니다. +block.mechanical-pump.description = 느린 속도로 물을 퍼올리는 펌프입니다. 대신 전력이 필요없습니다. block.rotary-pump.description = 일반 물 펌프보다 더 빠른 속도로 물을 끌어올릴 수 있는 펌프입니다. -block.thermal-pump.description = 기계식 펌프보다 3배 빠른 속도로 액체를 퍼올릴 수 있는 펌프이며, 용암도 퍼올릴 수 있는 유일한 펌프입니다. -block.router.description = 한 방향에서 아이템을 받은 후 최대 3개의 다른 방향으로 동일하게 출력합니다.\n재료를 한곳에서 여러 대상으로 분할하여 운반하는데 유용합니다. +block.thermal-pump.description = 최고의 펌프. +block.router.description = 한 방향에서 아이템을 널은 후 최대 3개의 다른 방향으로 균등하게 출력합니다. 재료를 한곳에서 여러 개의 목표로 분할하는 데 유용합니다. block.distributor.description = 아이템을 최대 7개의 다른 방향으로 똑같이 분할하는 고급 분배기. block.bridge-conveyor.description = 고급 자원 수송 블록.\n지형이나 건물을 넘어 최대 3개 타일을 건너뛰고 자원을 운송할 수 있습니다. -block.item-source.description = 자원을 선택하면 그 자원이 무한하게 생성되는 블록입니다. -block.liquid-source.description = 무한한 액체를 출력해냅니다. -block.item-void.description = 아이템을 사라지게 만듭니다. -block.power-source.description = 무한한 전력을 공급해주는 블록입니다. +block.item-source.description = 자원을 선택하면 그 자원이 무한하게 생성되는 블록입니다. 샌드박스 전용. +block.liquid-source.description = 무한한 액체를 출력해냅니다. 샌드박스 전용. +block.item-void.description = 아이템을 사라지게 만듭니다. 샌드박스 전용. +block.power-source.description = 무한한 전력을 공급해주는 블록입니다. 샌드박스 전용. block.power-void.description = 설정된 아이템을 계속해서 출력하는 블록입니다. -liquid.water.description = 지상 유닛이 이 위를 지나가면 이동속도가 느려지고, 깊은 물에 빠지면 죽습니다. -liquid.oil.description = 일부 조합 블록에서 사용되는 자원입니다. -liquid.cryofluid.description = 포탑 및 토륨 원자로에서 사용되는 자원입니다. +liquid.water.description = 일반적으로 냉각기와 폐기물 처리에 사용된다. +liquid.oil.description = 연소, 폭발 또는 냉각제로 사용될 수 있다. +liquid.cryofluid.description = 건물을 냉각시키는데 가장 효과적인 액체. diff --git a/core/assets/bundles/bundle_nl.properties b/core/assets/bundles/bundle_nl.properties index 627ed142be..233e9fb109 100644 --- a/core/assets/bundles/bundle_nl.properties +++ b/core/assets/bundles/bundle_nl.properties @@ -192,11 +192,26 @@ editor.oregen.info = Ore Generation: editor.mapinfo = Map Info editor.author = Author: editor.description = Description: +editor.waves = Waves: +waves.title = Waves +waves.remove = Remove +waves.never = +waves.every = every +waves.waves = wave(s) +waves.perspawn = per spawn +waves.to = to +waves.boss = Boss +editor.default = [LIGHT_GRAY] +edit = Edit... editor.name = Name: editor.teams = Teams editor.elevation = Elevation -editor.errorimageload = Error loading file:\n[accent]{0} -editor.errorimagesave = Error saving file:\n[accent]{0} +editor.errorload = Error loading file:\n[accent]{0} +editor.errorsave = Error saving file:\n[accent]{0} +editor.errorname = Map has no name defined. +editor.update = Update +editor.randomize = Randomize +editor.apply = Apply editor.generate = Generate editor.resize = Resize editor.loadmap = Load Map @@ -225,6 +240,21 @@ editor.mapname = Map Name: editor.overwrite = [accent]Warning!\nThis overwrites an existing map. editor.overwrite.confirm = [scarlet]Warning![] A map with this name already exists. Are you sure you want to overwrite it? editor.selectmap = Select a map to load: +filter.distort = Distort +filter.noise = Noise +filter.ore = Ore +filter.rivernoise = River Noise +filter.scatter = Scatter +filter.terrain = Terrain +filter.option.scale = Scale +filter.option.mag = Magnitude +filter.option.threshold = Threshold +filter.option.circle-scale = Circle Scale +filter.option.octaves = Octaves +filter.option.falloff = Falloff +filter.option.floor = Floor +filter.option.wall = Wall +filter.option.ore = Ore width = Width: height = Height: menu = Menu @@ -273,14 +303,9 @@ zone.groundZero.name = Ground Zero zone.craters.name = The Craters zone.frozenForest.name = Frozen Forest zone.ruinousShores.name = Ruinous Shores -zone.crags.name = Crags zone.stainedMountains.name = Stained Mountains -zone.impact0079.name = Impact 0079 zone.desolateRift.name = Desolate Rift -zone.arcticDesert.name = Arctic Desert -zone.dryWastes.name = Dry Wastes zone.nuclearComplex.name = Nuclear Production Complex -zone.moltenFault.name = Molten Fault settings.language = Language settings.reset = Reset to Defaults settings.rebind = Rebind @@ -300,6 +325,7 @@ info.title = Info error.title = [crimson]An error has occured error.crashtitle = An error has occured blocks.outputspeed = Drill Speed: {0}/s +blocks.efficiency = Efficiency: {0}% blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = Block Info blocks.powerbalance = Power: {0} @@ -307,6 +333,7 @@ blocks.poweroutput = Power Output: {0} blocks.powercapacity = Power Capacity blocks.powershot = Power/Shot blocks.targetsair = Targets Air +blocks.items = Items: {0} blocks.itemsmoved = Move Speed blocks.shootrange = Range blocks.size = Size @@ -369,6 +396,7 @@ category.items = Items category.crafting = Crafting category.shooting = Shooting category.optional = Optional Enhancements +setting.animatedwater.name = Animated Water setting.indicators.name = Ally Indicators setting.autotarget.name = Auto-Target setting.fpscap.name = Max FPS @@ -523,6 +551,15 @@ mech.ability = [LIGHT_GRAY]Ability: {0} liquid.heatcapacity = [LIGHT_GRAY]Heat Capacity: {0} liquid.viscosity = [LIGHT_GRAY]Viscosity: {0} liquid.temperature = [LIGHT_GRAY]Temperature: {0} +block.grass.name = Grass +block.salt.name = Salt +block.sandrocks.name = Sand Rocks +block.spore-pine.name = Spore Pine +block.shale.name = Shale +block.shale-boulder.name = Shale Boulder +block.moss.name = Moss +block.spore-moss.name = Spore Moss +block.shalerocks.name = Shale Rocks block.scrap-wall.name = Scrap Wall block.scrap-wall-large.name = Large Scrap Wall block.scrap-wall-huge.name = Huge Scrap Wall @@ -557,13 +594,6 @@ block.pine.name = Pine block.white-tree-dead.name = White Tree Dead block.white-tree.name = White Tree block.spore-cluster.name = Spore Cluster -block.stained-rocks.name = Stained Rocks -block.stained-stone.name = Stained Stone -block.stained-rocks-red.name = Stained Rocks Red -block.stained-stone-red.name = Stained Stone Red -block.stained-rocks-yellow.name = Stained Rocks Yellow -block.stained-stone-yellow.name = Stained Stone Yellow -block.stained-boulder.name = Stained Boulder block.metal-floor.name = Metal Floor block.metal-floor-2.name = Metal Floor 2 block.metal-floor-3.name = Metal Floor 3 @@ -584,6 +614,7 @@ block.thorium-wall-large.name = Large Thorium Wall block.door.name = Door block.door-large.name = Large Door block.duo.name = Duo +block.scatter.name = Scatter block.hail.name = Hail block.lancer.name = Lancer block.conveyor.name = Conveyor @@ -650,6 +681,7 @@ block.phantom-factory.name = Phantom Drone Factory block.wraith-factory.name = Wraith Fighter Factory block.ghoul-factory.name = Ghoul Bomber Factory block.dagger-factory.name = Dagger Mech Factory +block.crawler-factory.name = Crawler Mech Factory block.titan-factory.name = Titan Mech Factory block.fortress-factory.name = Fortress Mech Factory block.revenant-factory.name = Revenant Fighter Factory @@ -745,6 +777,7 @@ block.overdrive-projector.description = Increases the speed of nearby buildings block.force-projector.description = Creates a hexagonal force field around itself, protecting buildings and units inside from damage through bullets. block.shock-mine.description = Damages enemies stepping on the mine. Nearly invisible to the enemy. block.duo.description = A small, cheap turret. +block.scatter.description = A medium-sized anti-air turret. Sprays clumps of lead or scrap flak at enemy units. block.arc.description = A small turret which shoots electricity in a random arc towards the enemy. block.hail.description = A small artillery turret. block.lancer.description = A medium-sized turret which shoots charged electricity beams. diff --git a/core/assets/bundles/bundle_pl.properties b/core/assets/bundles/bundle_pl.properties index bab1016b6a..ef419aaf6c 100644 --- a/core/assets/bundles/bundle_pl.properties +++ b/core/assets/bundles/bundle_pl.properties @@ -192,11 +192,26 @@ editor.oregen.info = Generacja złóż: editor.mapinfo = Informacje o mapie editor.author = Autor: editor.description = Opis: +editor.waves = Waves: +waves.title = Waves +waves.remove = Remove +waves.never = +waves.every = every +waves.waves = wave(s) +waves.perspawn = per spawn +waves.to = to +waves.boss = Boss +editor.default = [LIGHT_GRAY] +edit = Edit... editor.name = Nazwa: editor.teams = Drużyny editor.elevation = Poziom terenu -editor.errorimageload = Błąd podczas ładowania pliku obrazu: [accent]{0} -editor.errorimagesave = Błąd podczas zapisywania pliku obrazu: [accent]{0} +editor.errorload = Error loading file:\n[accent]{0} +editor.errorsave = Error saving file:\n[accent]{0} +editor.errorname = Map has no name defined. +editor.update = Update +editor.randomize = Randomize +editor.apply = Apply editor.generate = Generuj editor.resize = Zmień rozmiar editor.loadmap = Załaduj mapę @@ -225,6 +240,21 @@ editor.mapname = Nazwa mapy: editor.overwrite = [accent]Uwaga!\nSpowoduje to nadpisanie istniejącej mapy. editor.overwrite.confirm = [scarlet]Uwaga![] Mapa pod tą nazwą już istnieje. Jesteś pewny, że chcesz ją nadpisać? editor.selectmap = Wybierz mapę do załadowania: +filter.distort = Distort +filter.noise = Noise +filter.ore = Ore +filter.rivernoise = River Noise +filter.scatter = Scatter +filter.terrain = Terrain +filter.option.scale = Scale +filter.option.mag = Magnitude +filter.option.threshold = Threshold +filter.option.circle-scale = Circle Scale +filter.option.octaves = Octaves +filter.option.falloff = Falloff +filter.option.floor = Floor +filter.option.wall = Wall +filter.option.ore = Ore width = Szerokość: height = Wysokość: menu = Menu @@ -273,14 +303,9 @@ zone.groundZero.name = Wybuch Lądowy zone.craters.name = Kratery zone.frozenForest.name = Zamrożony Las zone.ruinousShores.name = Zniszczone Przybrzerza -zone.crags.name = Urwiska zone.stainedMountains.name = Zabarwione Góry -zone.impact0079.name = Uderzenie 0079 zone.desolateRift.name = Ponura Szczelina -zone.arcticDesert.name = Lodowa Pustynia -zone.dryWastes.name = Suche Pustki zone.nuclearComplex.name = Centrum Wyrobu Jądrowego -zone.moltenFault.name = Stopiony Uskok settings.language = Język settings.reset = Przywróć domyślne settings.rebind = Zmień przyciski @@ -300,6 +325,7 @@ info.title = [accent]Informacje error.title = [crimson]Wystąpił błąd error.crashtitle = Wystąpił błąd blocks.outputspeed = Drill Speed: {0}/s +blocks.efficiency = Efficiency: {0}% blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = Informacje o bloku blocks.powerbalance = Power: {0} @@ -307,6 +333,7 @@ blocks.poweroutput = Power Output: {0} blocks.powercapacity = Pojemność mocy blocks.powershot = moc/strzał blocks.targetsair = Może namierzać wrogów powietrznych +blocks.items = Items: {0} blocks.itemsmoved = Move Speed blocks.shootrange = Zasięg blocks.size = Rozmiar @@ -369,6 +396,7 @@ category.items = Przedmioty category.crafting = Przetwórstwo category.shooting = Strzelanie category.optional = Ulepszenia Nieobowiąskowe +setting.animatedwater.name = Animated Water setting.indicators.name = Wskaźniki Przyjaciół setting.autotarget.name = Automatyczne Celowanie setting.fpscap.name = Maksymalny FPS @@ -523,6 +551,15 @@ mech.ability = [LIGHT_GRAY]Umiejętność: {0} liquid.heatcapacity = [LIGHT_GRAY]Wytrzymałość na przegrzewanie: {0} liquid.viscosity = [LIGHT_GRAY]Lepkość: {0} liquid.temperature = [LIGHT_GRAY]Temperatura: {0} +block.grass.name = Grass +block.salt.name = Salt +block.sandrocks.name = Sand Rocks +block.spore-pine.name = Spore Pine +block.shale.name = Shale +block.shale-boulder.name = Shale Boulder +block.moss.name = Moss +block.spore-moss.name = Spore Moss +block.shalerocks.name = Shale Rocks block.scrap-wall.name = Scrap Wall block.scrap-wall-large.name = Large Scrap Wall block.scrap-wall-huge.name = Huge Scrap Wall @@ -557,13 +594,6 @@ block.pine.name = Pine block.white-tree-dead.name = White Tree Dead block.white-tree.name = White Tree block.spore-cluster.name = Spore Cluster -block.stained-rocks.name = Stained Rocks -block.stained-stone.name = Stained Stone -block.stained-rocks-red.name = Stained Rocks Red -block.stained-stone-red.name = Stained Stone Red -block.stained-rocks-yellow.name = Stained Rocks Yellow -block.stained-stone-yellow.name = Stained Stone Yellow -block.stained-boulder.name = Stained Boulde block.metal-floor.name = Metal Floor block.metal-floor-2.name = Metal Floor 2 block.metal-floor-3.name = Metal Floor 3 @@ -584,6 +614,7 @@ block.thorium-wall-large.name = Duża Torowa Ściana block.door.name = Drzwi block.door-large.name = Duże drzwi block.duo.name = Podwójne działko +block.scatter.name = Scatter block.hail.name = Święte działko block.lancer.name = Lancer block.conveyor.name = Przenośnik @@ -650,6 +681,7 @@ block.phantom-factory.name = Fabryka Dronów Widmo block.wraith-factory.name = Fabryka Wojowników Zjawa block.ghoul-factory.name = Fabryka Bombowców Upiór block.dagger-factory.name = Fabryka Mechów Nóż +block.crawler-factory.name = Crawler Mech Factory block.titan-factory.name = Fabryka Mechów Tytan block.fortress-factory.name = Fabryka Mechów Fortreca block.revenant-factory.name = Fabryka Wojowników Potwór @@ -745,6 +777,7 @@ block.overdrive-projector.description = Increases the speed of nearby buildings block.force-projector.description = Creates a hexagonal force field around itself, protecting buildings and units inside from damage through bullets. block.shock-mine.description = Damages enemies stepping on the mine. Nearly invisible to the enemy. block.duo.description = A small, cheap turret. +block.scatter.description = A medium-sized anti-air turret. Sprays clumps of lead or scrap flak at enemy units. block.arc.description = A small turret which shoots electricity in a random arc towards the enemy. block.hail.description = A small artillery turret. block.lancer.description = A medium-sized turret which shoots charged electricity beams. diff --git a/core/assets/bundles/bundle_pt_BR.properties b/core/assets/bundles/bundle_pt_BR.properties index 02e46340da..8796b94bb7 100644 --- a/core/assets/bundles/bundle_pt_BR.properties +++ b/core/assets/bundles/bundle_pt_BR.properties @@ -192,11 +192,26 @@ editor.oregen.info = Geração de minério: editor.mapinfo = Informação do mapa editor.author = Autor: editor.description = Descrição: +editor.waves = Waves: +waves.title = Waves +waves.remove = Remove +waves.never = +waves.every = every +waves.waves = wave(s) +waves.perspawn = per spawn +waves.to = to +waves.boss = Boss +editor.default = [LIGHT_GRAY] +edit = Edit... editor.name = Nome: editor.teams = Time editor.elevation = Elevação -editor.errorimageload = Erro ao carregar arquivo de imagem:\n[accent]{0} -editor.errorimagesave = Erro ao salvar arquivo de imagem:\n[accent]{0} +editor.errorload = Error loading file:\n[accent]{0} +editor.errorsave = Error saving file:\n[accent]{0} +editor.errorname = Map has no name defined. +editor.update = Update +editor.randomize = Randomize +editor.apply = Apply editor.generate = Gerar editor.resize = Redimen\n sionar editor.loadmap = Carregar\n Mapa @@ -225,6 +240,21 @@ editor.mapname = Nome do Mapa: editor.overwrite = [accent]Aviso!\nIsso Subistitui um mapa existente. editor.overwrite.confirm = [scarlet]Aviso![] Um mapa com esse nome já existe. Tem certeza que deseja substituir? editor.selectmap = Selecione uma mapa para carregar: +filter.distort = Distort +filter.noise = Noise +filter.ore = Ore +filter.rivernoise = River Noise +filter.scatter = Scatter +filter.terrain = Terrain +filter.option.scale = Scale +filter.option.mag = Magnitude +filter.option.threshold = Threshold +filter.option.circle-scale = Circle Scale +filter.option.octaves = Octaves +filter.option.falloff = Falloff +filter.option.floor = Floor +filter.option.wall = Wall +filter.option.ore = Ore width = Largura: height = Altura: menu = Menu @@ -273,14 +303,9 @@ zone.groundZero.name = Ground Zero zone.craters.name = The Craters zone.frozenForest.name = Frozen Forest zone.ruinousShores.name = Ruinous Shores -zone.crags.name = Crags zone.stainedMountains.name = Stained Mountains -zone.impact0079.name = Impact 0079 zone.desolateRift.name = Desolate Rift -zone.arcticDesert.name = Arctic Desert -zone.dryWastes.name = Dry Wastes zone.nuclearComplex.name = Nuclear Production Complex -zone.moltenFault.name = Molten Fault settings.language = Linguagem settings.reset = Restaurar Padrões settings.rebind = Religar @@ -300,6 +325,7 @@ info.title = [accent]Informação error.title = [crimson]Ocorreu um Erro. error.crashtitle = Ocorreu um Erro blocks.outputspeed = Drill Speed: {0}/s +blocks.efficiency = Efficiency: {0}% blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = Informação do Bloco blocks.powerbalance = Power: {0} @@ -307,6 +333,7 @@ blocks.poweroutput = Power Output: {0} blocks.powercapacity = Capacidade de Energia blocks.powershot = Energia/tiro blocks.targetsair = Mirar no ar +blocks.items = Items: {0} blocks.itemsmoved = Move Speed blocks.shootrange = Alcance blocks.size = Tamanho @@ -369,6 +396,7 @@ category.items = Itens category.crafting = Construindo category.shooting = Atirando category.optional = Melhoras opcionais +setting.animatedwater.name = Animated Water setting.indicators.name = Ally Indicators setting.autotarget.name = Alvo automatico setting.fpscap.name = FPS Maximo @@ -523,6 +551,15 @@ mech.ability = [LIGHT_GRAY]Habilidade: {0} liquid.heatcapacity = [LIGHT_GRAY]Capacidade de aquecimento: {0} liquid.viscosity = [LIGHT_GRAY]Viscosidade: {0} liquid.temperature = [LIGHT_GRAY]Temperatura: {0} +block.grass.name = Grass +block.salt.name = Salt +block.sandrocks.name = Sand Rocks +block.spore-pine.name = Spore Pine +block.shale.name = Shale +block.shale-boulder.name = Shale Boulder +block.moss.name = Moss +block.spore-moss.name = Spore Moss +block.shalerocks.name = Shale Rocks block.scrap-wall.name = Scrap Wall block.scrap-wall-large.name = Large Scrap Wall block.scrap-wall-huge.name = Huge Scrap Wall @@ -557,13 +594,6 @@ block.pine.name = Pine block.white-tree-dead.name = White Tree Dead block.white-tree.name = White Tree block.spore-cluster.name = Spore Cluster -block.stained-rocks.name = Stained Rocks -block.stained-stone.name = Stained Stone -block.stained-rocks-red.name = Stained Rocks Red -block.stained-stone-red.name = Stained Stone Red -block.stained-rocks-yellow.name = Stained Rocks Yellow -block.stained-stone-yellow.name = Stained Stone Yellow -block.stained-boulder.name = Stained Boulde block.metal-floor.name = Metal Floor block.metal-floor-2.name = Metal Floor 2 block.metal-floor-3.name = Metal Floor 3 @@ -584,6 +614,7 @@ block.thorium-wall-large.name = Parede larga de tório block.door.name = Porta block.door-large.name = Porta Grande block.duo.name = Dupla +block.scatter.name = Scatter block.hail.name = Hail block.lancer.name = Lancador block.conveyor.name = Esteira @@ -650,6 +681,7 @@ block.phantom-factory.name = Fabrica de Drone Phantom block.wraith-factory.name = Fabrica de Drone Wraith block.ghoul-factory.name = Fabrica de Bombardeiro Ghoul block.dagger-factory.name = Fabrica de mech Dagger +block.crawler-factory.name = Crawler Mech Factory block.titan-factory.name = Fabrica de mech titan block.fortress-factory.name = Fabrica de mech Fortress block.revenant-factory.name = Fabrica de lutadores Revenant @@ -745,6 +777,7 @@ block.overdrive-projector.description = Aumenta a velocidade de unidades proxima block.force-projector.description = Cria um campo de forca hexagonal em volta de si mesmo, Protegendo construções e unidades dentro de dano por balas. block.shock-mine.description = Danifica inimigos em cima da mina. Quase invisivel ao inimigo. block.duo.description = Uma torre pequena e barata. +block.scatter.description = A medium-sized anti-air turret. Sprays clumps of lead or scrap flak at enemy units. block.arc.description = Uma pequena torre que atira eletricidade em um pequeno arc aleatoriamente no inimigo. block.hail.description = Uma pequena torre de artilharia. block.lancer.description = Uma torre de Tamanho-Medio que atira raios de eletricidade. diff --git a/core/assets/bundles/bundle_ru.properties b/core/assets/bundles/bundle_ru.properties index c81158f62d..25d8792463 100644 --- a/core/assets/bundles/bundle_ru.properties +++ b/core/assets/bundles/bundle_ru.properties @@ -192,11 +192,26 @@ editor.oregen.info = Генерация Руд: editor.mapinfo = Информация о карте editor.author = Автор: editor.description = Описание: +editor.waves = Waves: +waves.title = Waves +waves.remove = Remove +waves.never = +waves.every = every +waves.waves = wave(s) +waves.perspawn = per spawn +waves.to = to +waves.boss = Boss +editor.default = [LIGHT_GRAY] +edit = Edit... editor.name = Название: editor.teams = Команды editor.elevation = Возвышенность -editor.errorimageload = Ошибка загрузки изображения: [accent] {0} -editor.errorimagesave = Ошибка сохранения изображения: [accent] {0} +editor.errorload = Error loading file:\n[accent]{0} +editor.errorsave = Error saving file:\n[accent]{0} +editor.errorname = Map has no name defined. +editor.update = Update +editor.randomize = Randomize +editor.apply = Apply editor.generate = Создать editor.resize = Изменить \nразмер editor.loadmap = Загрузить\nкарту @@ -225,6 +240,21 @@ editor.mapname = Название карты: editor.overwrite = [accent]Внимание! \nЭто перезапишет уже существующую карту. editor.overwrite.confirm = [scarlet]Осторожно![] Карта с таким названием уже существует. Вы действительно хотите её перезаписать? editor.selectmap = Выберите карту для загрузки: +filter.distort = Distort +filter.noise = Noise +filter.ore = Ore +filter.rivernoise = River Noise +filter.scatter = Scatter +filter.terrain = Terrain +filter.option.scale = Scale +filter.option.mag = Magnitude +filter.option.threshold = Threshold +filter.option.circle-scale = Circle Scale +filter.option.octaves = Octaves +filter.option.falloff = Falloff +filter.option.floor = Floor +filter.option.wall = Wall +filter.option.ore = Ore width = Ширина: height = Высота: menu = Меню @@ -273,14 +303,9 @@ zone.groundZero.name = Нулевая земля zone.craters.name = Кратеры zone.frozenForest.name = Ледяной Лес zone.ruinousShores.name = Разрушенные Берега -zone.crags.name = Утёсы zone.stainedMountains.name = Окрашенные горы -zone.impact0079.name = Удар 0079 zone.desolateRift.name = Пустынный Разлом -zone.arcticDesert.name = Арктическия Пустыня -zone.dryWastes.name = Грязные Отходы zone.nuclearComplex.name = Ядерный Производственный Комплекс -zone.moltenFault.name = Расплавленый Разлом settings.language = Язык settings.reset = Сбросить по умолчанию settings.rebind = Смена @@ -300,6 +325,7 @@ info.title = Информация error.title = [crimson]Произошла ошибка error.crashtitle = Произошла ошибка blocks.outputspeed = Drill Speed: {0}/s +blocks.efficiency = Efficiency: {0}% blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = Информация о блоке blocks.powerbalance = Энергия: {0} @@ -307,6 +333,7 @@ blocks.poweroutput = Выходная энергия: {0} blocks.powercapacity = Вместимость энергии blocks.powershot = Энергия/выстрел blocks.targetsair = Атакует воздуш. юнитов +blocks.items = Items: {0} blocks.itemsmoved = Скорость перемещения blocks.shootrange = Радиус действия blocks.size = Размер @@ -369,6 +396,7 @@ category.items = Предметы category.crafting = Создание category.shooting = Cтрельба category.optional = Дополнительные улучшения +setting.animatedwater.name = Animated Water setting.indicators.name = Показывать в сторону союзников setting.autotarget.name = Авто-цель setting.fpscap.name = Макс. FPS @@ -523,6 +551,15 @@ mech.ability = [LIGHT_GRAY]Способность: {0} liquid.heatcapacity = [LIGHT_GRAY]Теплоёмкость: {0} liquid.viscosity = [LIGHT_GRAY]Вязкость: {0} liquid.temperature = [LIGHT_GRAY]Температура: {0} +block.grass.name = Grass +block.salt.name = Salt +block.sandrocks.name = Sand Rocks +block.spore-pine.name = Spore Pine +block.shale.name = Shale +block.shale-boulder.name = Shale Boulder +block.moss.name = Moss +block.spore-moss.name = Spore Moss +block.shalerocks.name = Shale Rocks block.scrap-wall.name = Стена из металлолома block.scrap-wall-large.name = Великая стена из металлолома block.scrap-wall-huge.name = Огромная стена из металлолома @@ -557,13 +594,6 @@ block.pine.name = Сосна block.white-tree-dead.name = Мёртвое Белое Дерево block.white-tree.name = Белое Дерево block.spore-cluster.name = Скопление спор -block.stained-rocks.name = Пятнистые Камни -block.stained-stone.name = Пятнистый Камень -block.stained-rocks-red.name = Красные Пятнистые Камни -block.stained-stone-red.name = Красный Пятнистый Камень -block.stained-rocks-yellow.name = Жёлтые Пятнистые Камни -block.stained-stone-yellow.name = Жёлтый Пятнистый Камень -block.stained-boulder.name = Пятнистый Валун block.metal-floor.name = Металлический Пол block.metal-floor-2.name = Металлический Пол 2 block.metal-floor-3.name = Металлический Пол 3 @@ -584,6 +614,7 @@ block.thorium-wall-large.name = Большая ториевая стена block.door.name = Дверь block.door-large.name = Большая дверь block.duo.name = Двойная турель +block.scatter.name = Scatter block.hail.name = Град block.lancer.name = Копейщик block.conveyor.name = Конвейер @@ -650,6 +681,7 @@ block.phantom-factory.name = Завод дронов "Фантом" block.wraith-factory.name = Завод призрачных истребителей block.ghoul-factory.name = Завод бомбардировщиков "Гуль" block.dagger-factory.name = Завод мехов "Кинджал" +block.crawler-factory.name = Crawler Mech Factory block.titan-factory.name = Завод мехов "Титан" block.fortress-factory.name = Завод мехов "Крепость" block.revenant-factory.name = Завод бомбардировщиков "Потусторонний убийца" @@ -745,6 +777,7 @@ block.overdrive-projector.description = Ускоряет в небольшом block.force-projector.description = Создаёт в небольшом радиусе силовое поле, которое защищает от атак противника. block.shock-mine.description = Поставьте её на землю. Она бьётся ЭЛЕКТРИЧЕСТВОМ О_О block.duo.description = Маленькая и дешёвая турель. +block.scatter.description = A medium-sized anti-air turret. Sprays clumps of lead or scrap flak at enemy units. block.arc.description = Турель с малым радиусом атаки. В качестве патронов требует воду или криогенную жидкость. Также нужна энергия. block.hail.description = Дальнобойная начальная турель.\nИспользует в качестве снарядов плотный сплав, кремний и пиротит.\nДля ускорения стрельбы можно подвести воду и криогенную жидкость. block.lancer.description = Турель, которая стреляет лазером на среднее расстояние.\nИспользует в качестве снарядов энергию.\nДля ускорения стрельбы можно подвести воду или криогенную жидкость. diff --git a/core/assets/bundles/bundle_tk.properties b/core/assets/bundles/bundle_tk.properties index 5561216c7b..6485aac7b9 100644 --- a/core/assets/bundles/bundle_tk.properties +++ b/core/assets/bundles/bundle_tk.properties @@ -192,11 +192,26 @@ editor.oregen.info = Maden Yaratilmasi: editor.mapinfo = Harita bilgisi: editor.author = Yapimci: editor.description = Yorum: +editor.waves = Waves: +waves.title = Waves +waves.remove = Remove +waves.never = +waves.every = every +waves.waves = wave(s) +waves.perspawn = per spawn +waves.to = to +waves.boss = Boss +editor.default = [LIGHT_GRAY] +edit = Edit... editor.name = isim: editor.teams = Takimlar editor.elevation = Yukseklik -editor.errorimageload = Dosya yuklenemedi:\n[accent]{0} -editor.errorimagesave = Dosya kaydedilemedi.:\n[accent]{0} +editor.errorload = Error loading file:\n[accent]{0} +editor.errorsave = Error saving file:\n[accent]{0} +editor.errorname = Map has no name defined. +editor.update = Update +editor.randomize = Randomize +editor.apply = Apply editor.generate = Yarat editor.resize = Boyutunu degistir editor.loadmap = Harita yukle @@ -225,6 +240,21 @@ editor.mapname = Harita ismi: editor.overwrite = [accent]Dikkat et!\nBu bir haritanin uzerinden cececek. editor.overwrite.confirm = [scarlet]uyari![] bu isimde bir harita zaten var. Uzerinden gececek misin? editor.selectmap = Yukleyecek bir harita sec: +filter.distort = Distort +filter.noise = Noise +filter.ore = Ore +filter.rivernoise = River Noise +filter.scatter = Scatter +filter.terrain = Terrain +filter.option.scale = Scale +filter.option.mag = Magnitude +filter.option.threshold = Threshold +filter.option.circle-scale = Circle Scale +filter.option.octaves = Octaves +filter.option.falloff = Falloff +filter.option.floor = Floor +filter.option.wall = Wall +filter.option.ore = Ore width = Genislik: height = Yukseklik: menu = Menu @@ -273,14 +303,9 @@ zone.groundZero.name = Ground Zero zone.craters.name = The Craters zone.frozenForest.name = Frozen Forest zone.ruinousShores.name = Ruinous Shores -zone.crags.name = Crags zone.stainedMountains.name = Stained Mountains -zone.impact0079.name = Impact 0079 zone.desolateRift.name = Desolate Rift -zone.arcticDesert.name = Arctic Desert -zone.dryWastes.name = Dry Wastes zone.nuclearComplex.name = Nuclear Production Complex -zone.moltenFault.name = Molten Fault settings.language = Dil settings.reset = ilk ayarlara geri al settings.rebind = Geri al @@ -300,6 +325,7 @@ info.title = [accent]Bilgi error.title = [crimson]Bir hata olustu error.crashtitle = Bir hata olustu blocks.outputspeed = Drill Speed: {0}/s +blocks.efficiency = Efficiency: {0}% blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = Yapi bilgisi blocks.powerbalance = Power: {0} @@ -307,6 +333,7 @@ blocks.poweroutput = Power Output: {0} blocks.powercapacity = Guc kapasitesi blocks.powershot = Guc/Saldiri hizi blocks.targetsair = Havayi hedef alir mi? +blocks.items = Items: {0} blocks.itemsmoved = Move Speed blocks.shootrange = Menzil blocks.size = Buyukluk @@ -369,6 +396,7 @@ category.items = esyalar category.crafting = uretim category.shooting = sikma category.optional = Optional Enhancements +setting.animatedwater.name = Animated Water setting.indicators.name = Ally Indicators setting.autotarget.name = Auto-Target setting.fpscap.name = Max FPS @@ -523,6 +551,15 @@ mech.ability = [LIGHT_GRAY]yetenek gucu: {0} liquid.heatcapacity = [LIGHT_GRAY]isinma kapasitesi: {0} liquid.viscosity = [LIGHT_GRAY]Yari sivilik: {0} liquid.temperature = [LIGHT_GRAY]isi: {0} +block.grass.name = Grass +block.salt.name = Salt +block.sandrocks.name = Sand Rocks +block.spore-pine.name = Spore Pine +block.shale.name = Shale +block.shale-boulder.name = Shale Boulder +block.moss.name = Moss +block.spore-moss.name = Spore Moss +block.shalerocks.name = Shale Rocks block.scrap-wall.name = Scrap Wall block.scrap-wall-large.name = Large Scrap Wall block.scrap-wall-huge.name = Huge Scrap Wall @@ -557,13 +594,6 @@ block.pine.name = Pine block.white-tree-dead.name = White Tree Dead block.white-tree.name = White Tree block.spore-cluster.name = Spore Cluster -block.stained-rocks.name = Stained Rocks -block.stained-stone.name = Stained Stone -block.stained-rocks-red.name = Stained Rocks Red -block.stained-stone-red.name = Stained Stone Red -block.stained-rocks-yellow.name = Stained Rocks Yellow -block.stained-stone-yellow.name = Stained Stone Yellow -block.stained-boulder.name = Stained Boulde block.metal-floor.name = Metal Floor block.metal-floor-2.name = Metal Floor 2 block.metal-floor-3.name = Metal Floor 3 @@ -584,6 +614,7 @@ block.thorium-wall-large.name = genis toryum duvari block.door.name = kapi block.door-large.name = genis kapi block.duo.name = ikili +block.scatter.name = Scatter block.hail.name = yagdirici block.lancer.name = Lazer topu block.conveyor.name = konvenyor @@ -650,6 +681,7 @@ block.phantom-factory.name = Phantom Drone Factory block.wraith-factory.name = Wraith Fighter Factory block.ghoul-factory.name = Ghoul Bomber Factory block.dagger-factory.name = Dagger Mech Factory +block.crawler-factory.name = Crawler Mech Factory block.titan-factory.name = Titan Mech Factory block.fortress-factory.name = Fortress Mech Factory block.revenant-factory.name = Revenant Fighter Factory @@ -745,6 +777,7 @@ block.overdrive-projector.description = Increases the speed of nearby buildings block.force-projector.description = Creates a hexagonal force field around itself, protecting buildings and units inside from damage through bullets. block.shock-mine.description = Damages enemies stepping on the mine. Nearly invisible to the enemy. block.duo.description = A small, cheap turret. +block.scatter.description = A medium-sized anti-air turret. Sprays clumps of lead or scrap flak at enemy units. block.arc.description = A small turret which shoots electricity in a random arc towards the enemy. block.hail.description = A small artillery turret. block.lancer.description = A medium-sized turret which shoots charged electricity beams. diff --git a/core/assets/bundles/bundle_tr.properties b/core/assets/bundles/bundle_tr.properties index 7f109d2189..bb1641547c 100644 --- a/core/assets/bundles/bundle_tr.properties +++ b/core/assets/bundles/bundle_tr.properties @@ -192,11 +192,26 @@ editor.oregen.info = Ore Generation: editor.mapinfo = Map Info editor.author = Author: editor.description = Description: +editor.waves = Waves: +waves.title = Waves +waves.remove = Remove +waves.never = +waves.every = every +waves.waves = wave(s) +waves.perspawn = per spawn +waves.to = to +waves.boss = Boss +editor.default = [LIGHT_GRAY] +edit = Edit... editor.name = Name: editor.teams = Teams editor.elevation = Elevation -editor.errorimageload = Resim dosyası yüklenirken hata oluştu: [accent] {0} -editor.errorimagesave = Resim dosyası kaydedilirken hata oluştu: [accent] {0} +editor.errorload = Error loading file:\n[accent]{0} +editor.errorsave = Error saving file:\n[accent]{0} +editor.errorname = Map has no name defined. +editor.update = Update +editor.randomize = Randomize +editor.apply = Apply editor.generate = Üretmek editor.resize = Yeniden Boyutlandırma editor.loadmap = Harita Yükle @@ -225,6 +240,21 @@ editor.mapname = Harita Adı editor.overwrite = [Vurgu] Uyarı! Bu mevcut bir haritanın üzerine yazar. editor.overwrite.confirm = [scarlet]Warning![] A map with this name already exists. Are you sure you want to overwrite it? editor.selectmap = Yüklenecek bir harita seçin: +filter.distort = Distort +filter.noise = Noise +filter.ore = Ore +filter.rivernoise = River Noise +filter.scatter = Scatter +filter.terrain = Terrain +filter.option.scale = Scale +filter.option.mag = Magnitude +filter.option.threshold = Threshold +filter.option.circle-scale = Circle Scale +filter.option.octaves = Octaves +filter.option.falloff = Falloff +filter.option.floor = Floor +filter.option.wall = Wall +filter.option.ore = Ore width = Genişliği: height = Boy: menu = Menü @@ -273,14 +303,9 @@ zone.groundZero.name = Ground Zero zone.craters.name = The Craters zone.frozenForest.name = Frozen Forest zone.ruinousShores.name = Ruinous Shores -zone.crags.name = Crags zone.stainedMountains.name = Stained Mountains -zone.impact0079.name = Impact 0079 zone.desolateRift.name = Desolate Rift -zone.arcticDesert.name = Arctic Desert -zone.dryWastes.name = Dry Wastes zone.nuclearComplex.name = Nuclear Production Complex -zone.moltenFault.name = Molten Fault settings.language = Dil settings.reset = Varsayılanlara Dön settings.rebind = Rebind @@ -300,6 +325,7 @@ info.title = [Vurgu] Bilgi error.title = [crimson] Bir hata oluştu error.crashtitle = Bir hata oluştu blocks.outputspeed = Drill Speed: {0}/s +blocks.efficiency = Efficiency: {0}% blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = Blok Bilgisi blocks.powerbalance = Power: {0} @@ -307,6 +333,7 @@ blocks.poweroutput = Power Output: {0} blocks.powercapacity = Güç kapasitesi blocks.powershot = Güç / atış blocks.targetsair = Targets Air +blocks.items = Items: {0} blocks.itemsmoved = Move Speed blocks.shootrange = Range blocks.size = Boyut @@ -369,6 +396,7 @@ category.items = Items category.crafting = Crafting category.shooting = Shooting category.optional = Optional Enhancements +setting.animatedwater.name = Animated Water setting.indicators.name = Ally Indicators setting.autotarget.name = Auto-Target setting.fpscap.name = Max FPS @@ -523,6 +551,15 @@ mech.ability = [LIGHT_GRAY]Ability: {0} liquid.heatcapacity = [LIGHT_GRAY]Heat Capacity: {0} liquid.viscosity = [LIGHT_GRAY]Viscosity: {0} liquid.temperature = [LIGHT_GRAY]Temperature: {0} +block.grass.name = Grass +block.salt.name = Salt +block.sandrocks.name = Sand Rocks +block.spore-pine.name = Spore Pine +block.shale.name = Shale +block.shale-boulder.name = Shale Boulder +block.moss.name = Moss +block.spore-moss.name = Spore Moss +block.shalerocks.name = Shale Rocks block.scrap-wall.name = Scrap Wall block.scrap-wall-large.name = Large Scrap Wall block.scrap-wall-huge.name = Huge Scrap Wall @@ -557,13 +594,6 @@ block.pine.name = Pine block.white-tree-dead.name = White Tree Dead block.white-tree.name = White Tree block.spore-cluster.name = Spore Cluster -block.stained-rocks.name = Stained Rocks -block.stained-stone.name = Stained Stone -block.stained-rocks-red.name = Stained Rocks Red -block.stained-stone-red.name = Stained Stone Red -block.stained-rocks-yellow.name = Stained Rocks Yellow -block.stained-stone-yellow.name = Stained Stone Yellow -block.stained-boulder.name = Stained Boulde block.metal-floor.name = Metal Floor block.metal-floor-2.name = Metal Floor 2 block.metal-floor-3.name = Metal Floor 3 @@ -584,6 +614,7 @@ block.thorium-wall-large.name = Large Thorium Wall block.door.name = kapı block.door-large.name = büyük kapı block.duo.name = Duo +block.scatter.name = Scatter block.hail.name = Hail block.lancer.name = Lancer block.conveyor.name = konveyör @@ -650,6 +681,7 @@ block.phantom-factory.name = Phantom Drone Factory block.wraith-factory.name = Wraith Fighter Factory block.ghoul-factory.name = Ghoul Bomber Factory block.dagger-factory.name = Dagger Mech Factory +block.crawler-factory.name = Crawler Mech Factory block.titan-factory.name = Titan Mech Factory block.fortress-factory.name = Fortress Mech Factory block.revenant-factory.name = Revenant Fighter Factory @@ -745,6 +777,7 @@ block.overdrive-projector.description = Increases the speed of nearby buildings block.force-projector.description = Creates a hexagonal force field around itself, protecting buildings and units inside from damage through bullets. block.shock-mine.description = Damages enemies stepping on the mine. Nearly invisible to the enemy. block.duo.description = A small, cheap turret. +block.scatter.description = A medium-sized anti-air turret. Sprays clumps of lead or scrap flak at enemy units. block.arc.description = A small turret which shoots electricity in a random arc towards the enemy. block.hail.description = A small artillery turret. block.lancer.description = A medium-sized turret which shoots charged electricity beams. diff --git a/core/assets/bundles/bundle_uk_UA.properties b/core/assets/bundles/bundle_uk_UA.properties index 0400870ee6..97c191b6f7 100644 --- a/core/assets/bundles/bundle_uk_UA.properties +++ b/core/assets/bundles/bundle_uk_UA.properties @@ -192,11 +192,26 @@ editor.oregen.info = Генерація руд: editor.mapinfo = Інформація про мапу editor.author = Автор: editor.description = Опис: +editor.waves = Waves: +waves.title = Waves +waves.remove = Remove +waves.never = +waves.every = every +waves.waves = wave(s) +waves.perspawn = per spawn +waves.to = to +waves.boss = Boss +editor.default = [LIGHT_GRAY] +edit = Edit... editor.name = Назва: editor.teams = Команди editor.elevation = Висота -editor.errorimageload = Помилка завантаження зображення:[accent] {0} -editor.errorimagesave = Помилка збереження зображення:\n[accent]{0} +editor.errorload = Error loading file:\n[accent]{0} +editor.errorsave = Error saving file:\n[accent]{0} +editor.errorname = Map has no name defined. +editor.update = Update +editor.randomize = Randomize +editor.apply = Apply editor.generate = Створити editor.resize = Змінити \nрозмір editor.loadmap = Завантажити мапу @@ -225,6 +240,21 @@ editor.mapname = Название карты: editor.overwrite = [accent]Попередження!\nЦе перезаписує існуючу карту. editor.overwrite.confirm = [scarlet]Попередження![] Карта з такою назвою вже існує. Ви впевнені, що хочете переписати її? editor.selectmap = Виберіть мапу для завантаження: +filter.distort = Distort +filter.noise = Noise +filter.ore = Ore +filter.rivernoise = River Noise +filter.scatter = Scatter +filter.terrain = Terrain +filter.option.scale = Scale +filter.option.mag = Magnitude +filter.option.threshold = Threshold +filter.option.circle-scale = Circle Scale +filter.option.octaves = Octaves +filter.option.falloff = Falloff +filter.option.floor = Floor +filter.option.wall = Wall +filter.option.ore = Ore width = Ширина: height = Висота: menu = Меню @@ -273,14 +303,9 @@ zone.groundZero.name = Нульова земля zone.craters.name = Кратери zone.frozenForest.name = Крижаний Ліс zone.ruinousShores.name = Зруйновані Берега -zone.crags.name = Кручі zone.stainedMountains.name = Пофарбовані гори -zone.impact0079.name = Impact 0079 zone.desolateRift.name = Пустельний Розлом -zone.arcticDesert.name = Арктична Пустеля -zone.dryWastes.name = Брудні Відходи zone.nuclearComplex.name = Ядерний Виробничий Комплекс -zone.moltenFault.name = РозплавленийРозлом settings.language = Мова settings.reset = Скинути за замовчуванням settings.rebind = Зміна @@ -300,6 +325,7 @@ info.title = Інформація error.title = [crimson]Виникла помилка error.crashtitle = Виникла помилка blocks.outputspeed = Drill Speed: {0}/s +blocks.efficiency = Efficiency: {0}% blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = Інформація про блок blocks.powerbalance = Енергія: {0} @@ -307,6 +333,7 @@ blocks.poweroutput = Вихідна енергія: {0} blocks.powercapacity = Місткість енергії blocks.powershot = Енергія/постріл blocks.targetsair = Атакуе повітряних ворогів +blocks.items = Items: {0} blocks.itemsmoved = Швидкість переміщення blocks.shootrange = Діапазон дії blocks.size = Розмір @@ -369,6 +396,7 @@ category.items = Предмети category.crafting = Створення category.shooting = Стрільба category.optional = Додаткові поліпшення +setting.animatedwater.name = Animated Water setting.indicators.name = Показувати у сторону союзників setting.autotarget.name = Авто-ціль setting.fpscap.name = Макс. FPS @@ -523,6 +551,15 @@ mech.ability = [LIGHT_GRAY]Здібність: {0} liquid.heatcapacity = [LIGHT_GRAY]Теплоємність: {0} liquid.viscosity = [LIGHT_GRAY]В'язкість: {0} liquid.temperature = [LIGHT_GRAY]Температура: {0} +block.grass.name = Grass +block.salt.name = Salt +block.sandrocks.name = Sand Rocks +block.spore-pine.name = Spore Pine +block.shale.name = Shale +block.shale-boulder.name = Shale Boulder +block.moss.name = Moss +block.spore-moss.name = Spore Moss +block.shalerocks.name = Shale Rocks block.scrap-wall.name = Стіна з металобрухту block.scrap-wall-large.name = Велика стіна з металобрухту block.scrap-wall-huge.name = Величезна стіна з металобрухту @@ -557,13 +594,6 @@ block.pine.name = Сосна block.white-tree-dead.name = Мертве Біле Дерево block.white-tree.name = Біле Дерево block.spore-cluster.name = Скупчення спор -block.stained-rocks.name = Плямисті Камені -block.stained-stone.name = Плямистий Камінь -block.stained-rocks-red.name = Червоні Плямисті Камні -block.stained-stone-red.name = Червоний Плямистий Камінь -block.stained-rocks-yellow.name = Жовті Плямисті Камні -block.stained-stone-yellow.name = Жовтий Плямистий Камінь -block.stained-boulder.name = Плямистий Валун block.metal-floor.name = Металевий Пол block.metal-floor-2.name = Металевий Пол 2 block.metal-floor-3.name = Металевий Пол 3 @@ -584,6 +614,7 @@ block.thorium-wall-large.name = Велика торієва стіна block.door.name = Двері block.door-large.name = Великі двері block.duo.name = Подвійна +block.scatter.name = Scatter block.hail.name = Град block.lancer.name = Списоносець block.conveyor.name = Конвеєр @@ -650,6 +681,7 @@ block.phantom-factory.name = Завод дронов "Фантом" block.wraith-factory.name = Завод винищувачів "Примара" block.ghoul-factory.name = Завод бомбардувальників-винищувачів "Ґуль" block.dagger-factory.name = Завод мехів "Кинджал" +block.crawler-factory.name = Crawler Mech Factory block.titan-factory.name = Завод мехів "Титан" block.fortress-factory.name = Завод мехів "Крепость" block.revenant-factory.name = Завод бомбардировщиков "Потусторонний убийца" @@ -745,6 +777,7 @@ block.overdrive-projector.description = Прискорює в невеликом block.force-projector.description = Створює в невеликому радіусі силове поле, яке захищає від атак супротивника. block.shock-mine.description = Поставте її на землю. Вона б'ється ЕЛЕКТРИКОЮ О_О block.duo.description = Маленька і дешева турель.\nДля прискорення стрільби можна підвести воду або кріогенну рідина. +block.scatter.description = A medium-sized anti-air turret. Sprays clumps of lead or scrap flak at enemy units. block.arc.description = Турель с малым радиусом атаки.\nДля прискорення стрільби можна підвести воду або кріогенну рідину. block.hail.description = Далекобійна початкова турель.\nДля прискорення стрільби можна підвести воду або кріогенну рідину. block.lancer.description = Турель, яка стріляє лазером на середню відстань.\nДля прискорення стрільби можна підвести воду або кріогенну рідину. diff --git a/core/assets/bundles/bundle_zh_CN.properties b/core/assets/bundles/bundle_zh_CN.properties index 8cbb346913..f9677c7ca9 100644 --- a/core/assets/bundles/bundle_zh_CN.properties +++ b/core/assets/bundles/bundle_zh_CN.properties @@ -192,11 +192,26 @@ editor.oregen.info = 生成矿石: editor.mapinfo = 地图详情 editor.author = 作者: editor.description = 描述: +editor.waves = Waves: +waves.title = Waves +waves.remove = Remove +waves.never = +waves.every = every +waves.waves = wave(s) +waves.perspawn = per spawn +waves.to = to +waves.boss = Boss +editor.default = [LIGHT_GRAY] +edit = Edit... editor.name = 名字: editor.teams = 团队 editor.elevation = 高度 -editor.errorimageload = 载入文件时出错:\n[accent]{0} -editor.errorimagesave = 保存文件时出错:\n[accent]{0} +editor.errorload = Error loading file:\n[accent]{0} +editor.errorsave = Error saving file:\n[accent]{0} +editor.errorname = Map has no name defined. +editor.update = Update +editor.randomize = Randomize +editor.apply = Apply editor.generate = 生成 editor.resize = 调整 editor.loadmap = 载入地图 @@ -225,6 +240,21 @@ editor.mapname = 地图名字: editor.overwrite = [accent]警告!\n这将会覆盖一个已经存在的地图。 editor.overwrite.confirm = [scarlet]警告![] 存在同名地图,确定要覆盖? editor.selectmap = 选择一个地图加载: +filter.distort = Distort +filter.noise = Noise +filter.ore = Ore +filter.rivernoise = River Noise +filter.scatter = Scatter +filter.terrain = Terrain +filter.option.scale = Scale +filter.option.mag = Magnitude +filter.option.threshold = Threshold +filter.option.circle-scale = Circle Scale +filter.option.octaves = Octaves +filter.option.falloff = Falloff +filter.option.floor = Floor +filter.option.wall = Wall +filter.option.ore = Ore width = 宽度: height = 高度: menu = 菜单 @@ -273,14 +303,9 @@ zone.groundZero.name = Ground Zero zone.craters.name = The Craters zone.frozenForest.name = Frozen Forest zone.ruinousShores.name = Ruinous Shores -zone.crags.name = Crags zone.stainedMountains.name = Stained Mountains -zone.impact0079.name = Impact 0079 zone.desolateRift.name = Desolate Rift -zone.arcticDesert.name = Arctic Desert -zone.dryWastes.name = Dry Wastes zone.nuclearComplex.name = Nuclear Production Complex -zone.moltenFault.name = Molten Fault settings.language = 语言 settings.reset = 恢复默认 settings.rebind = 重新绑定 @@ -300,6 +325,7 @@ info.title = [accent]详情 error.title = [crimson]发生了一个错误 error.crashtitle = 发生了一个错误 blocks.outputspeed = Drill Speed: {0}/s +blocks.efficiency = Efficiency: {0}% blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = 方块详情 blocks.powerbalance = Power: {0} @@ -307,6 +333,7 @@ blocks.poweroutput = Power Output: {0} blocks.powercapacity = 能量容量 blocks.powershot = 能量/发射 blocks.targetsair = 攻击空中单位 +blocks.items = Items: {0} blocks.itemsmoved = 移动速度 blocks.shootrange = 范围 blocks.size = 尺寸 @@ -369,6 +396,7 @@ category.items = 物品 category.crafting = 制造 category.shooting = 发射 category.optional = 可选的增强物品 +setting.animatedwater.name = Animated Water setting.indicators.name = 队友指示器 setting.autotarget.name = 自动发射 setting.fpscap.name = 最高 FPS @@ -523,6 +551,15 @@ mech.ability = [LIGHT_GRAY]能力:{0} liquid.heatcapacity = [LIGHT_GRAY]热容量:{0} liquid.viscosity = [LIGHT_GRAY]粘度:{0} liquid.temperature = [LIGHT_GRAY]温度:{0} +block.grass.name = Grass +block.salt.name = Salt +block.sandrocks.name = Sand Rocks +block.spore-pine.name = Spore Pine +block.shale.name = Shale +block.shale-boulder.name = Shale Boulder +block.moss.name = Moss +block.spore-moss.name = Spore Moss +block.shalerocks.name = Shale Rocks block.scrap-wall.name = Scrap Wall block.scrap-wall-large.name = Large Scrap Wall block.scrap-wall-huge.name = Huge Scrap Wall @@ -557,13 +594,6 @@ block.pine.name = Pine block.white-tree-dead.name = White Tree Dead block.white-tree.name = White Tree block.spore-cluster.name = Spore Cluster -block.stained-rocks.name = Stained Rocks -block.stained-stone.name = Stained Stone -block.stained-rocks-red.name = Stained Rocks Red -block.stained-stone-red.name = Stained Stone Red -block.stained-rocks-yellow.name = Stained Rocks Yellow -block.stained-stone-yellow.name = Stained Stone Yellow -block.stained-boulder.name = Stained Boulde block.metal-floor.name = Metal Floor block.metal-floor-2.name = Metal Floor 2 block.metal-floor-3.name = Metal Floor 3 @@ -584,6 +614,7 @@ block.thorium-wall-large.name = 大型钍墙 block.door.name = 门 block.door-large.name = 大门 block.duo.name = 双管炮 +block.scatter.name = Scatter block.hail.name = 冰雹炮 block.lancer.name = 蓝瑟炮 block.conveyor.name = 传送带 @@ -650,6 +681,7 @@ block.phantom-factory.name = 鬼怪无人机工厂 block.wraith-factory.name = 幻影战机工厂 block.ghoul-factory.name = 食尸鬼轰炸机工厂 block.dagger-factory.name = 尖刀机甲工厂 +block.crawler-factory.name = Crawler Mech Factory block.titan-factory.name = 泰坦机甲工厂 block.fortress-factory.name = 堡垒机甲工厂 block.revenant-factory.name = 亡魂战机工厂 @@ -745,6 +777,7 @@ block.overdrive-projector.description = 提高附近建筑物的速度,如钻 block.force-projector.description = 自身周围创建一个六边形力场,保护建筑物和内部单位免受子弹的伤害。 block.shock-mine.description = 伤害踩到它的敌人。敌人几乎看不到它。 block.duo.description = 小而便宜的炮塔。 +block.scatter.description = A medium-sized anti-air turret. Sprays clumps of lead or scrap flak at enemy units. block.arc.description = 小型炮塔,发射电弧。 block.hail.description = 小型炮兵炮台。 block.lancer.description = 中型炮塔,发射带电的电子束。 diff --git a/core/assets/bundles/bundle_zh_TW.properties b/core/assets/bundles/bundle_zh_TW.properties index 8f96dc5461..772d9d6e89 100644 --- a/core/assets/bundles/bundle_zh_TW.properties +++ b/core/assets/bundles/bundle_zh_TW.properties @@ -192,11 +192,26 @@ editor.oregen.info = 礦石產生: editor.mapinfo = 地圖資訊 editor.author = 作者: editor.description = 描述: +editor.waves = Waves: +waves.title = Waves +waves.remove = Remove +waves.never = +waves.every = every +waves.waves = wave(s) +waves.perspawn = per spawn +waves.to = to +waves.boss = Boss +editor.default = [LIGHT_GRAY] +edit = Edit... editor.name = 名稱: editor.teams = 隊伍 editor.elevation = 高度 -editor.errorimageload = 載入圖像檔時發生錯誤:[accent]{0} -editor.errorimagesave = 儲存圖像檔時發生錯誤:[橙色]{0} +editor.errorload = Error loading file:\n[accent]{0} +editor.errorsave = Error saving file:\n[accent]{0} +editor.errorname = Map has no name defined. +editor.update = Update +editor.randomize = Randomize +editor.apply = Apply editor.generate = 產生 editor.resize = 調整大小 editor.loadmap = 載入地圖 @@ -225,6 +240,21 @@ editor.mapname = 地圖名稱: editor.overwrite = [accent]警告!這將會覆蓋現有的地圖。 editor.overwrite.confirm = [scarlet]警告![]同名地圖存在,確定要覆蓋現有地圖? editor.selectmap = 選取要載入的地圖: +filter.distort = Distort +filter.noise = Noise +filter.ore = Ore +filter.rivernoise = River Noise +filter.scatter = Scatter +filter.terrain = Terrain +filter.option.scale = Scale +filter.option.mag = Magnitude +filter.option.threshold = Threshold +filter.option.circle-scale = Circle Scale +filter.option.octaves = Octaves +filter.option.falloff = Falloff +filter.option.floor = Floor +filter.option.wall = Wall +filter.option.ore = Ore width = 寬度: height = 長度: menu = 主選單 @@ -273,14 +303,9 @@ zone.groundZero.name = Ground Zero zone.craters.name = The Craters zone.frozenForest.name = Frozen Forest zone.ruinousShores.name = Ruinous Shores -zone.crags.name = Crags zone.stainedMountains.name = Stained Mountains -zone.impact0079.name = Impact 0079 zone.desolateRift.name = Desolate Rift -zone.arcticDesert.name = Arctic Desert -zone.dryWastes.name = Dry Wastes zone.nuclearComplex.name = Nuclear Production Complex -zone.moltenFault.name = Molten Fault settings.language = 語言 settings.reset = 重設為預設設定 settings.rebind = 重新綁定 @@ -300,6 +325,7 @@ info.title = [accent]資訊 error.title = [crimson]發生錯誤 error.crashtitle = 發生錯誤 blocks.outputspeed = Drill Speed: {0}/s +blocks.efficiency = Efficiency: {0}% blocks.unknown = [LIGHT_GRAY]??? blocks.blockinfo = 方塊資訊 blocks.powerbalance = Power: {0} @@ -307,6 +333,7 @@ blocks.poweroutput = Power Output: {0} blocks.powercapacity = 蓄電量 blocks.powershot = 能量/射擊 blocks.targetsair = 攻擊空中目標 +blocks.items = Items: {0} blocks.itemsmoved = Move Speed blocks.shootrange = 範圍 blocks.size = 尺寸 @@ -369,6 +396,7 @@ category.items = 物品 category.crafting = 合成 category.shooting = 射擊 category.optional = 可選的強化 +setting.animatedwater.name = Animated Water setting.indicators.name = 盟友指標 setting.autotarget.name = 自動射擊 setting.fpscap.name = 最大FPS @@ -523,6 +551,15 @@ mech.ability = [LIGHT_GRAY]能力:{0} liquid.heatcapacity = [LIGHT_GRAY]熱容量:{0} liquid.viscosity = [LIGHT_GRAY]粘性:{0} liquid.temperature = [LIGHT_GRAY]温度:{0} +block.grass.name = Grass +block.salt.name = Salt +block.sandrocks.name = Sand Rocks +block.spore-pine.name = Spore Pine +block.shale.name = Shale +block.shale-boulder.name = Shale Boulder +block.moss.name = Moss +block.spore-moss.name = Spore Moss +block.shalerocks.name = Shale Rocks block.scrap-wall.name = Scrap Wall block.scrap-wall-large.name = Large Scrap Wall block.scrap-wall-huge.name = Huge Scrap Wall @@ -557,13 +594,6 @@ block.pine.name = Pine block.white-tree-dead.name = White Tree Dead block.white-tree.name = White Tree block.spore-cluster.name = Spore Cluster -block.stained-rocks.name = Stained Rocks -block.stained-stone.name = Stained Stone -block.stained-rocks-red.name = Stained Rocks Red -block.stained-stone-red.name = Stained Stone Red -block.stained-rocks-yellow.name = Stained Rocks Yellow -block.stained-stone-yellow.name = Stained Stone Yellow -block.stained-boulder.name = Stained Boulde block.metal-floor.name = Metal Floor block.metal-floor-2.name = Metal Floor 2 block.metal-floor-3.name = Metal Floor 3 @@ -584,6 +614,7 @@ block.thorium-wall-large.name = 大型釷牆 block.door.name = 門 block.door-large.name = 大門 block.duo.name = 雙炮 +block.scatter.name = Scatter block.hail.name = 冰雹炮 block.lancer.name = 藍瑟炮 block.conveyor.name = 輸送帶 @@ -650,6 +681,7 @@ block.phantom-factory.name = 幻影無人機工廠 block.wraith-factory.name = 怨靈戰鬥機工廠 block.ghoul-factory.name = 食屍鬼轟炸機工廠 block.dagger-factory.name = 匕首機甲工廠 +block.crawler-factory.name = Crawler Mech Factory block.titan-factory.name = 泰坦機甲工廠 block.fortress-factory.name = 堡壘機甲工廠 block.revenant-factory.name = 亡魂戰鬥機工廠 @@ -745,6 +777,7 @@ block.overdrive-projector.description = 提高附近建築物的速度,如鑽 block.force-projector.description = 在自身周圍形成一個六角形力場,保護內部的建築物和單位免受子彈的傷害。 block.shock-mine.description = 傷害踩到地雷的敵人。敵人幾乎看不見。 block.duo.description = 一種小而便宜的砲塔。 +block.scatter.description = A medium-sized anti-air turret. Sprays clumps of lead or scrap flak at enemy units. block.arc.description = 一種向敵人射出隨機電弧的小砲塔。 block.hail.description = 一種小型火砲。 block.lancer.description = 一種射出電子束的中型砲塔。 diff --git a/core/assets/cursors/cursor.png b/core/assets/cursors/cursor.png index ece5696be0..d8487b7fa1 100644 Binary files a/core/assets/cursors/cursor.png and b/core/assets/cursors/cursor.png differ diff --git a/core/assets/cursors/drill.png b/core/assets/cursors/drill.png index e524b82762..9672daf2e3 100644 Binary files a/core/assets/cursors/drill.png and b/core/assets/cursors/drill.png differ diff --git a/core/assets/cursors/hand.png b/core/assets/cursors/hand.png index 1613b1eac3..ef489d4554 100644 Binary files a/core/assets/cursors/hand.png and b/core/assets/cursors/hand.png differ diff --git a/core/assets/cursors/ibeam.png b/core/assets/cursors/ibeam.png index 61ddc4b423..7ce778a271 100644 Binary files a/core/assets/cursors/ibeam.png and b/core/assets/cursors/ibeam.png differ diff --git a/core/assets/cursors/unload.png b/core/assets/cursors/unload.png index 2340e6d94e..faa0fe9476 100644 Binary files a/core/assets/cursors/unload.png and b/core/assets/cursors/unload.png differ diff --git a/core/assets/fonts/font.ttf b/core/assets/fonts/font.ttf new file mode 100644 index 0000000000..3ccb1ada7c Binary files /dev/null and b/core/assets/fonts/font.ttf differ diff --git a/core/assets/fonts/pixel.ttf b/core/assets/fonts/pixel.ttf deleted file mode 100644 index 177fff5182..0000000000 Binary files a/core/assets/fonts/pixel.ttf and /dev/null differ diff --git a/core/assets/maps/craters.mmap b/core/assets/maps/craters.mmap index 6b614e442a..a0032dfdc3 100644 Binary files a/core/assets/maps/craters.mmap and b/core/assets/maps/craters.mmap differ diff --git a/core/assets/maps/desolateRift.mmap b/core/assets/maps/desolateRift.mmap index f6a9515fee..694353537d 100644 Binary files a/core/assets/maps/desolateRift.mmap and b/core/assets/maps/desolateRift.mmap differ diff --git a/core/assets/maps/fortress.mmap b/core/assets/maps/fortress.mmap new file mode 100644 index 0000000000..88fa55e854 Binary files /dev/null and b/core/assets/maps/fortress.mmap differ diff --git a/core/assets/maps/frozenForest.mmap b/core/assets/maps/frozenForest.mmap index 6b8bfc55f9..39ec3bb9ee 100644 Binary files a/core/assets/maps/frozenForest.mmap and b/core/assets/maps/frozenForest.mmap differ diff --git a/core/assets/maps/groundZero.mmap b/core/assets/maps/groundZero.mmap index b73cd867af..24bca59ae2 100644 Binary files a/core/assets/maps/groundZero.mmap and b/core/assets/maps/groundZero.mmap differ diff --git a/core/assets/maps/impact0079.mmap b/core/assets/maps/impact0079.mmap deleted file mode 100644 index 0353276104..0000000000 Binary files a/core/assets/maps/impact0079.mmap and /dev/null differ diff --git a/core/assets/maps/nuclearProductionComplex.mmap b/core/assets/maps/nuclearProductionComplex.mmap index dcffed46cc..d6385bf8a6 100644 Binary files a/core/assets/maps/nuclearProductionComplex.mmap and b/core/assets/maps/nuclearProductionComplex.mmap differ diff --git a/core/assets/maps/ruinousShores.mmap b/core/assets/maps/ruinousShores.mmap index 3f3ab56c34..a429d12525 100644 Binary files a/core/assets/maps/ruinousShores.mmap and b/core/assets/maps/ruinousShores.mmap differ diff --git a/core/assets/maps/stainedMountains.mmap b/core/assets/maps/stainedMountains.mmap index b57ae403d3..cbf23b9239 100644 Binary files a/core/assets/maps/stainedMountains.mmap and b/core/assets/maps/stainedMountains.mmap differ diff --git a/core/assets/shaders/fog.fragment b/core/assets/shaders/fog.fragment index ea94aa2f5a..7ac266711a 100644 --- a/core/assets/shaders/fog.fragment +++ b/core/assets/shaders/fog.fragment @@ -5,8 +5,6 @@ precision mediump int; uniform sampler2D u_texture; -const float round = 0.01; - varying vec4 v_color; varying vec2 v_texCoord; diff --git a/core/assets/shaders/mix.fragment b/core/assets/shaders/mix.fragment deleted file mode 100644 index 92c19f24a6..0000000000 --- a/core/assets/shaders/mix.fragment +++ /dev/null @@ -1,19 +0,0 @@ -#ifdef GL_ES -precision mediump float; -precision mediump int; -#endif - -uniform sampler2D u_texture; -uniform vec4 u_color; - -varying vec4 v_color; -varying vec2 v_texCoord; - -void main() { - - vec4 c = texture2D(u_texture, v_texCoord.xy); - - c = mix(c, vec4(u_color.rgb, c.a), v_color.a); - - gl_FragColor = c * vec4(v_color.rgb, 1.0); -} diff --git a/core/assets/shaders/shield.fragment b/core/assets/shaders/shield.fragment index f771e59dd3..cf8b6a7132 100644 --- a/core/assets/shaders/shield.fragment +++ b/core/assets/shaders/shield.fragment @@ -18,10 +18,6 @@ uniform vec2 u_offset; varying vec4 v_color; varying vec2 v_texCoord; -float round(float f){ - return float(int(f)); -} - void main() { vec2 T = v_texCoord.xy; @@ -41,7 +37,7 @@ void main() { }else{ if(color.a > 0.1){ - if(mod(coords.x / u_dp + coords.y / u_dp + sin(round(coords.x / u_dp) / 5.0) * 3.0 + sin(round(coords.y / u_dp) / 5.0) * 3.0 + u_time / 4.0, 10.0) < 2.0){ + if(mod(coords.x / u_dp + coords.y / u_dp + sin(floor(coords.x / u_dp) / 5.0) * 3.0 + sin(floor(coords.y / u_dp) / 5.0) * 3.0 + u_time / 4.0, 10.0) < 2.0){ color *= 1.65; } diff --git a/core/assets/shaders/tar.fragment b/core/assets/shaders/tar.fragment new file mode 100644 index 0000000000..98aeeeb9f6 --- /dev/null +++ b/core/assets/shaders/tar.fragment @@ -0,0 +1,73 @@ +#ifdef GL_ES +precision highp float; +precision mediump int; +#endif + +uniform sampler2D u_texture; + +uniform vec2 camerapos; +uniform vec2 screensize; +uniform float time; + +varying vec4 v_color; +varying vec2 v_texCoord; + +vec3 permute(vec3 x) { return mod(((x*34.0)+1.0)*x, 289.0); } + +float snoise(vec2 v){ + const vec4 C = vec4(0.211324865405187, 0.366025403784439, + -0.577350269189626, 0.024390243902439); + vec2 i = floor(v + dot(v, C.yy) ); + vec2 x0 = v - i + dot(i, C.xx); + vec2 i1; + i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); + vec4 x12 = x0.xyxy + C.xxzz; + x12.xy -= i1; + i = mod(i, 289.0); + vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 )) + + i.x + vec3(0.0, i1.x, 1.0 )); + vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), + dot(x12.zw,x12.zw)), 0.0); + m = m*m ; + m = m*m ; + vec3 x = 2.0 * fract(p * C.www) - 1.0; + vec3 h = abs(x) - 0.5; + vec3 ox = floor(x + 0.5); + vec3 a0 = x - ox; + m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h ); + vec3 g; + g.x = a0.x * x0.x + h.x * x0.y; + g.yz = a0.yz * x12.xz + h.yz * x12.yw; + return 130.0 * dot(m, g); +} + +void main() { + + vec2 c = v_texCoord.xy; + vec4 color = texture2D(u_texture, c); + + vec2 v = vec2(1.0/screensize.x, 1.0/screensize.y); + vec2 coords = vec2(c.x / v.x + camerapos.x, c.y / v.y + camerapos.y); + + float stime = time / 5.0; + + float mscl = 30.0; + float mth = 5.0; + + if(color.r > 0.01){ + color = texture2D(u_texture, c + vec2(sin(stime/3.0 + coords.y/0.75) * v.x, 0.0)) * vec4(0.9, 0.9, 1, 1.0); + color.a = 1.0; + + float n1 = snoise(coords / 22.0 + vec2(-time) / 540.0); + float n2 = snoise((coords + vec2(632.0)) / 8.0 + vec2(0.0, time) / 510.0); + + float r = (n1 + n2) / 2.0; + + if(r < -0.3 && r > -0.6){ + color *= 1.4; + color.a = 1.0; + } + } + + gl_FragColor = color; +} \ No newline at end of file diff --git a/core/assets/shaders/water.fragment b/core/assets/shaders/water.fragment new file mode 100644 index 0000000000..83910bbe5f --- /dev/null +++ b/core/assets/shaders/water.fragment @@ -0,0 +1,77 @@ +#ifdef GL_ES +precision highp float; +precision mediump int; +#endif + +uniform sampler2D u_texture; + +uniform vec2 camerapos; +uniform vec2 screensize; +uniform float time; + +varying vec4 v_color; +varying vec2 v_texCoord; + +vec3 permute(vec3 x) { return mod(((x*34.0)+1.0)*x, 289.0); } + +float snoise(vec2 v){ + const vec4 C = vec4(0.211324865405187, 0.366025403784439, + -0.577350269189626, 0.024390243902439); + vec2 i = floor(v + dot(v, C.yy) ); + vec2 x0 = v - i + dot(i, C.xx); + vec2 i1; + i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); + vec4 x12 = x0.xyxy + C.xxzz; + x12.xy -= i1; + i = mod(i, 289.0); + vec3 p = permute( permute( i.y + vec3(0.0, i1.y, 1.0 )) + + i.x + vec3(0.0, i1.x, 1.0 )); + vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x12.xy,x12.xy), + dot(x12.zw,x12.zw)), 0.0); + m = m*m ; + m = m*m ; + vec3 x = 2.0 * fract(p * C.www) - 1.0; + vec3 h = abs(x) - 0.5; + vec3 ox = floor(x + 0.5); + vec3 a0 = x - ox; + m *= 1.79284291400159 - 0.85373472095314 * ( a0*a0 + h*h ); + vec3 g; + g.x = a0.x * x0.x + h.x * x0.y; + g.yz = a0.yz * x12.xz + h.yz * x12.yw; + return 130.0 * dot(m, g); +} + +void main() { + + vec2 c = v_texCoord.xy; + vec4 color = texture2D(u_texture, c) * v_color; + + vec2 v = vec2(1.0/screensize.x, 1.0/screensize.y); + vec2 coords = vec2(c.x / v.x + camerapos.x, c.y / v.y + camerapos.y); + + float stime = time / 5.0; + + float mscl = 30.0; + float mth = 5.0; + + color = texture2D(u_texture, c + vec2(sin(stime/3.0 + coords.y/0.75) * v.x, 0.0)) * vec4(0.9, 0.9, 1, 1.0); + color.a = 1.0; + + float n1 = snoise(coords / 40.0 + vec2(time) / 200.0); + float n2 = snoise((coords + vec2(632.0)) / 25.0 + vec2(0.0, -time) / 190.0); + + float r = (n1 + n2) * 3.0; + + if(mod(float(int(coords.x + coords.y*1.1 + sin(stime / 8.0 + coords.x/5.0 - coords.y/100.0)*2.0)) + + sin(stime / 20.0 + coords.y/3.0) * 1.0 + + sin(stime / 10.0 + coords.y/2.0) * 2.0 + + sin(stime / 7.0 + coords.y/1.0) * 0.5 + + sin(coords.x + coords.y) + + sin(stime / 20.0 + coords.x/4.0) * 1.0, mscl) + r < mth){ + + color *= 1.2; + color.a = 1.0; + } + + gl_FragColor = color; +} \ No newline at end of file diff --git a/core/assets/sprites/background.png b/core/assets/sprites/background.png deleted file mode 100644 index ee3aa9ba6f..0000000000 Binary files a/core/assets/sprites/background.png and /dev/null differ diff --git a/core/assets/sprites/block_colors.png b/core/assets/sprites/block_colors.png index 6642bd33d3..cf39740b1b 100644 Binary files a/core/assets/sprites/block_colors.png and b/core/assets/sprites/block_colors.png differ diff --git a/core/assets/sprites/sprites.atlas b/core/assets/sprites/sprites.atlas index eb58551b70..dda7bf18ef 100644 --- a/core/assets/sprites/sprites.atlas +++ b/core/assets/sprites/sprites.atlas @@ -6,8414 +6,6258 @@ filter: Nearest,Nearest repeat: none force-projector rotate: false - xy: 1847, 1593 + xy: 415, 1530 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 force-projector-top rotate: false - xy: 453, 1214 + xy: 415, 1432 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 mend-projector rotate: false - xy: 771, 873 + xy: 1645, 1363 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 mend-projector-top rotate: false - xy: 705, 807 + xy: 1711, 1363 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 overdrive-projector rotate: false - xy: 771, 807 + xy: 1843, 1363 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 overdrive-projector-top rotate: false - xy: 705, 741 + xy: 1909, 1363 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 shock-mine rotate: false - xy: 1369, 318 + xy: 1489, 849 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conveyor rotate: false - xy: 1263, 510 + xy: 1551, 1168 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conveyor-bridge rotate: false - xy: 1275, 637 + xy: 1585, 1168 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conveyor-end rotate: false - xy: 1275, 603 + xy: 1619, 1168 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-0-0 rotate: false - xy: 1615, 579 + xy: 1817, 1100 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-0-1 rotate: false - xy: 579, 123 + xy: 1851, 1134 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-0-2 rotate: false - xy: 613, 123 + xy: 1851, 1100 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-0-3 rotate: false - xy: 647, 123 + xy: 1891, 1159 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-1-0 rotate: false - xy: 571, 89 + xy: 1925, 1159 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-1-1 rotate: false - xy: 571, 55 + xy: 1885, 1125 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-1-2 rotate: false - xy: 605, 89 + xy: 1919, 1125 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-1-3 rotate: false - xy: 571, 21 + xy: 1885, 1091 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-2-0 rotate: false - xy: 605, 55 + xy: 1919, 1091 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-2-1 rotate: false - xy: 639, 89 + xy: 1545, 1066 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-2-2 rotate: false - xy: 605, 21 + xy: 1579, 1066 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-2-3 rotate: false - xy: 639, 55 + xy: 1613, 1066 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-3-0 rotate: false - xy: 639, 21 + xy: 1647, 1066 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-3-1 rotate: false - xy: 1297, 569 + xy: 1681, 1066 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-3-2 rotate: false - xy: 1331, 569 + xy: 1715, 1066 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-3-3 rotate: false - xy: 1297, 535 + xy: 1749, 1066 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-4-0 rotate: false - xy: 1331, 535 + xy: 1783, 1066 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-4-1 rotate: false - xy: 1297, 501 + xy: 1817, 1066 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-4-2 rotate: false - xy: 1331, 501 + xy: 1851, 1066 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-4-3 rotate: false - xy: 1365, 556 + xy: 1885, 1057 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-0-0 rotate: false - xy: 1913, 281 + xy: 1151, 753 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-0-1 rotate: false - xy: 1947, 315 + xy: 1185, 863 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-0-2 rotate: false - xy: 1913, 247 + xy: 1185, 829 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-0-3 rotate: false - xy: 1947, 281 + xy: 1185, 795 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-1-0 rotate: false - xy: 1981, 315 + xy: 1185, 761 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-1-1 rotate: false - xy: 2015, 315 + xy: 1185, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-1-2 rotate: false - xy: 1947, 247 + xy: 1113, 745 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-1-3 rotate: false - xy: 1981, 281 + xy: 1108, 711 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-2-0 rotate: false - xy: 2015, 281 + xy: 1074, 700 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-2-1 rotate: false - xy: 1981, 247 + xy: 1108, 677 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-2-2 rotate: false - xy: 2015, 247 + xy: 1142, 711 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-2-3 rotate: false - xy: 1641, 213 + xy: 1142, 677 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-3-0 rotate: false - xy: 1675, 213 + xy: 1176, 693 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-3-1 rotate: false - xy: 1709, 213 + xy: 1176, 659 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-3-2 rotate: false - xy: 1743, 213 + xy: 1210, 693 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-3-3 rotate: false - xy: 1777, 213 + xy: 1210, 659 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-4-0 rotate: false - xy: 1811, 213 + xy: 495, 488 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-4-1 rotate: false - xy: 1845, 213 + xy: 495, 454 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-4-2 rotate: false - xy: 1879, 213 + xy: 495, 420 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-4-3 rotate: false - xy: 1913, 213 + xy: 495, 386 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 distributor rotate: false - xy: 733, 1005 + xy: 1249, 1429 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 junction rotate: false - xy: 1739, 451 + xy: 1913, 1023 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 mass-driver-base rotate: false - xy: 965, 1495 + xy: 1395, 1495 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 overflow-gate rotate: false - xy: 1759, 383 + xy: 1573, 930 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conveyor rotate: false - xy: 1861, 383 + xy: 1777, 930 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conveyor-arrow rotate: false - xy: 1895, 417 + xy: 1811, 930 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conveyor-bridge rotate: false - xy: 1895, 383 + xy: 1845, 930 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conveyor-end rotate: false - xy: 1929, 417 + xy: 1879, 921 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 router rotate: false - xy: 1199, 340 + xy: 1727, 896 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 sorter rotate: false - xy: 1471, 281 + xy: 1999, 879 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 blast-drill rotate: false - xy: 323, 1376 + xy: 1, 601 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 blast-drill-rim rotate: false - xy: 323, 1246 + xy: 1, 341 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 blast-drill-rotator rotate: false - xy: 323, 1116 + xy: 1, 211 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 blast-drill-top rotate: false - xy: 526, 1821 + xy: 1, 81 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 laser-drill rotate: false - xy: 649, 1365 + xy: 905, 1561 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 laser-drill-rim rotate: false - xy: 747, 1365 + xy: 1003, 1577 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 laser-drill-rotator rotate: false - xy: 649, 1267 + xy: 1003, 1479 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 laser-drill-top rotate: false - xy: 747, 1267 + xy: 1101, 1593 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 mechanical-drill rotate: false - xy: 639, 873 + xy: 1381, 1363 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 mechanical-drill-rotator rotate: false - xy: 705, 873 + xy: 1513, 1363 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 mechanical-drill-top rotate: false - xy: 639, 741 + xy: 1579, 1363 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 oil-extractor rotate: false - xy: 1259, 1495 + xy: 1591, 1593 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 oil-extractor-liquid rotate: false - xy: 1455, 1495 + xy: 1689, 1593 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 oil-extractor-rotator rotate: false - xy: 1553, 1495 + xy: 1689, 1495 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 oil-extractor-top rotate: false - xy: 1651, 1495 + xy: 1787, 1593 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 pneumatic-drill rotate: false - xy: 421, 175 + xy: 1645, 1297 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 pneumatic-drill-rotator rotate: false - xy: 813, 543 + xy: 1777, 1297 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 pneumatic-drill-top rotate: false - xy: 847, 477 + xy: 1843, 1297 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 water-extractor rotate: false - xy: 969, 707 + xy: 319, 904 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 water-extractor-liquid rotate: false - xy: 879, 641 + xy: 451, 1036 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 water-extractor-rotator rotate: false - xy: 879, 575 + xy: 319, 838 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 water-extractor-top rotate: false - xy: 945, 641 + xy: 385, 904 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -char1 - rotate: false - xy: 1309, 637 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -char2 - rotate: false - xy: 1309, 603 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -char3 - rotate: false - xy: 1332, 671 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -cliffs1 - rotate: false - xy: 1343, 637 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -coal1 - rotate: false - xy: 1343, 603 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -coal2 - rotate: false - xy: 1366, 692 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -coal3 - rotate: false - xy: 1400, 692 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -copper1 - rotate: false - xy: 1399, 556 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -copper2 - rotate: false - xy: 1365, 522 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -copper3 - rotate: false - xy: 1399, 522 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -craters1 - rotate: false - xy: 1501, 519 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -craters2 - rotate: false - xy: 1535, 545 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -craters3 - rotate: false - xy: 1569, 545 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -craters4 - rotate: false - xy: 1603, 545 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -craters5 - rotate: false - xy: 1535, 511 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -stone1 - rotate: false - xy: 1535, 511 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -craters6 - rotate: false - xy: 1569, 511 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -stone2 - rotate: false - xy: 1569, 511 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -deepwater - rotate: false - xy: 1467, 485 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -differential-generator - rotate: false - xy: 1651, 1593 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -differential-generator-top - rotate: false - xy: 1749, 1593 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -dunerocks-large - rotate: false - xy: 713, 939 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -dunerocks1 - rotate: false - xy: 1637, 477 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -dunerocks2 - rotate: false - xy: 1651, 621 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -edge-stencil-blocky - rotate: false - xy: 1, 799 - size: 288, 96 - orig: 288, 96 - offset: 0, 0 - index: -1 -edge-stencil-smooth - rotate: false - xy: 1, 701 - size: 288, 96 - orig: 288, 96 - offset: 0, 0 - index: -1 -grass1 - rotate: false - xy: 1683, 587 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -grass2 - rotate: false - xy: 1717, 587 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -grass3 - rotate: false - xy: 1751, 587 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -holostone1 - rotate: false - xy: 1853, 587 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -holostone2 - rotate: false - xy: 1887, 587 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -holostone3 - rotate: false - xy: 1921, 587 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -hotrock1 - rotate: false - xy: 1957, 621 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -hotrock2 - rotate: false - xy: 1955, 587 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -hotrock3 - rotate: false - xy: 1671, 553 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ice-edge - rotate: false - xy: 1, 505 - size: 288, 96 - orig: 288, 96 - offset: 0, 0 - index: -1 -ice-snow1 - rotate: false - xy: 1705, 519 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ice-snow2 - rotate: false - xy: 1739, 553 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ice-snow3 - rotate: false - xy: 1705, 485 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ice1 - rotate: false - xy: 1671, 519 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ice2 - rotate: false - xy: 1705, 553 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ice3 - rotate: false - xy: 1671, 485 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -icerocks-large - rotate: false - xy: 389, 45 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -icerocks1 - rotate: false - xy: 1739, 519 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -icerocks2 - rotate: false - xy: 1773, 553 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ignarock1 - rotate: false - xy: 1807, 553 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ignarock2 - rotate: false - xy: 1773, 485 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ignarock3 - rotate: false - xy: 1807, 519 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -lead1 - rotate: false - xy: 1943, 451 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -lead2 - rotate: false - xy: 1977, 451 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -lead3 - rotate: false - xy: 2011, 451 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -magmarock1 - rotate: false - xy: 1987, 961 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -magmarock2 - rotate: false - xy: 673, 81 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -magmarock3 - rotate: false - xy: 673, 47 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -metal-floor - rotate: false - xy: 741, 13 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -metal-floor-damaged5 - rotate: false - xy: 741, 13 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -metal-floor-2 - rotate: false - xy: 775, 43 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -metal-floor-3 - rotate: false - xy: 809, 43 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -metal-floor-5 - rotate: false - xy: 843, 43 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -metal-floor-damaged1 - rotate: false - xy: 877, 43 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -metal-floor-damaged2 - rotate: false - xy: 911, 43 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -metal-floor-damaged3 - rotate: false - xy: 945, 43 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -metal-floor-damaged4 - rotate: false - xy: 775, 9 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -metal-floor-damaged6 - rotate: false - xy: 809, 9 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -pine - rotate: false - xy: 1997, 417 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -rock1 - rotate: false - xy: 1727, 897 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -rock2 - rotate: false - xy: 1727, 847 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -rocks-large - rotate: false - xy: 1205, 1086 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -rocks1 - rotate: false - xy: 1165, 340 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -rocks2 - rotate: false - xy: 1233, 374 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -sand-water - rotate: false - xy: 1233, 272 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -sand1 - rotate: false - xy: 1131, 272 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -sand2 - rotate: false - xy: 1165, 272 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -sand3 - rotate: false - xy: 1199, 272 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -scrap1 - rotate: false - xy: 1267, 365 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -scrap2 - rotate: false - xy: 1301, 365 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -scrap3 - rotate: false - xy: 1267, 331 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -snow1 - rotate: false - xy: 1403, 349 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -snow2 - rotate: false - xy: 1403, 315 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -snow3 - rotate: false - xy: 1437, 349 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -snowrocks-large - rotate: false - xy: 1665, 1363 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -snowrocks1 - rotate: false - xy: 1403, 281 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -snowrocks2 - rotate: false - xy: 1437, 315 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -spore-cluster1 - rotate: false - xy: 2001, 755 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -spore-cluster2 - rotate: false - xy: 2001, 713 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -spore-cluster3 - rotate: false - xy: 1143, 696 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -stained-boulder1 - rotate: false - xy: 1505, 307 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -stained-boulder2 - rotate: false - xy: 1573, 341 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -stained-rocks-large - rotate: false - xy: 1831, 1297 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -stained-rocks-red-large - rotate: false - xy: 453, 441 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -stained-rocks-red1 - rotate: false - xy: 1607, 341 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -stained-rocks-red2 - rotate: false - xy: 1539, 273 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -stained-rocks-yellow-large - rotate: false - xy: 445, 375 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -stained-rocks-yellow1 - rotate: false - xy: 1573, 307 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -stained-rocks-yellow2 - rotate: false - xy: 1573, 273 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -stained-rocks1 - rotate: false - xy: 1505, 273 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -stained-rocks2 - rotate: false - xy: 1539, 307 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -stained-stone-red1 - rotate: false - xy: 1539, 239 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -stained-stone-red2 - rotate: false - xy: 1573, 239 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -stained-stone-red3 - rotate: false - xy: 1607, 239 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -stained-stone-yellow1 - rotate: false - xy: 1641, 315 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -stained-stone-yellow2 - rotate: false - xy: 1641, 281 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -stained-stone-yellow3 - rotate: false - xy: 1675, 315 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -stained-stone1 - rotate: false - xy: 1607, 307 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -stained-stone2 - rotate: false - xy: 1607, 273 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -stained-stone3 - rotate: false - xy: 1505, 239 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -stainedrocks-large - rotate: false - xy: 445, 309 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -stainedrocks1 - rotate: false - xy: 1641, 247 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -stainedrocks2 - rotate: false - xy: 1675, 281 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -stone3 - rotate: false - xy: 1709, 315 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -tar - rotate: false - xy: 1743, 281 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -thorium1 - rotate: false - xy: 1811, 315 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -thorium2 - rotate: false - xy: 1777, 247 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -thorium3 - rotate: false - xy: 1811, 281 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium1 - rotate: false - xy: 1879, 281 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium2 - rotate: false - xy: 1913, 315 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium3 - rotate: false - xy: 1879, 247 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -water - rotate: false - xy: 1071, 103 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -white-tree - rotate: false - xy: 1, 1317 - size: 320, 320 - orig: 320, 320 - offset: 0, 0 - index: -1 -white-tree-dead - rotate: false - xy: 1, 995 - size: 320, 320 - orig: 320, 320 - offset: 0, 0 - index: -1 block-border rotate: false - xy: 1161, 544 + xy: 1477, 1121 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-middle rotate: false - xy: 1195, 544 + xy: 1511, 1155 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pump-liquid rotate: false - xy: 1195, 544 + xy: 1511, 1155 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-select rotate: false - xy: 1229, 544 + xy: 1511, 1121 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-liquid rotate: false - xy: 1581, 613 + xy: 1681, 1134 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 place-arrow rotate: false - xy: 1847, 1495 + xy: 1885, 1593 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 rubble-1-0 rotate: false - xy: 1205, 1020 + xy: 253, 1003 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 rubble-1-1 rotate: false - xy: 1195, 954 + xy: 253, 937 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 rubble-2-0 rotate: false - xy: 1129, 914 + xy: 253, 871 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 rubble-2-1 rotate: false - xy: 1195, 888 + xy: 253, 805 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 rubble-3-0 rotate: false - xy: 845, 1201 + xy: 155, 1103 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 rubble-3-1 rotate: false - xy: 845, 1201 + xy: 155, 1103 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 rubble-4-0 rotate: false - xy: 1566, 1691 + xy: 1696, 1789 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 rubble-4-1 rotate: false - xy: 1566, 1691 + xy: 1696, 1789 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 spawn rotate: false - xy: 1403, 247 + xy: 1931, 845 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conduit rotate: false - xy: 1161, 510 + xy: 1409, 1079 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conduit-arrow rotate: false - xy: 1195, 510 + xy: 1443, 1087 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conveyor-arrow rotate: false - xy: 1195, 510 + xy: 1443, 1087 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conduit-bridge rotate: false - xy: 1229, 510 + xy: 1477, 1087 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conduit-end rotate: false - xy: 1263, 544 + xy: 1511, 1087 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom rotate: false - xy: 1411, 658 + xy: 1857, 1168 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-0 rotate: false - xy: 1411, 624 + xy: 1545, 1134 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-1 rotate: false - xy: 1445, 655 + xy: 1545, 1100 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-2 rotate: false - xy: 1479, 655 + xy: 1579, 1134 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-3 rotate: false - xy: 1513, 655 + xy: 1579, 1100 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-4 rotate: false - xy: 1445, 621 + xy: 1613, 1134 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-5 rotate: false - xy: 1479, 621 + xy: 1613, 1100 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-6 rotate: false - xy: 1513, 621 + xy: 1647, 1134 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-top-0 rotate: false - xy: 1615, 613 + xy: 1681, 1100 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-top-1 rotate: false - xy: 1377, 590 + xy: 1715, 1134 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-top-2 rotate: false - xy: 1411, 590 + xy: 1715, 1100 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-top-3 rotate: false - xy: 1445, 587 + xy: 1749, 1134 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-top-4 rotate: false - xy: 1479, 587 + xy: 1749, 1100 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-top-5 rotate: false - xy: 1513, 587 + xy: 1783, 1134 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-top-6 rotate: false - xy: 1547, 579 + xy: 1783, 1100 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-junction rotate: false - xy: 1945, 1129 + xy: 1981, 981 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-router-bottom rotate: false - xy: 1979, 1131 + xy: 1539, 964 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-router-liquid rotate: false - xy: 2013, 1147 + xy: 1607, 964 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-router-top rotate: false - xy: 2013, 1113 + xy: 1641, 964 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-tank-bottom rotate: false - xy: 747, 1169 + xy: 1199, 1593 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 liquid-tank-liquid rotate: false - xy: 649, 1071 + xy: 1297, 1593 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 liquid-tank-top rotate: false - xy: 747, 1071 + xy: 1297, 1495 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 mechanical-pump rotate: false - xy: 741, 81 + xy: 1879, 955 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conduit rotate: false - xy: 1793, 383 + xy: 1641, 930 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conduit-arrow rotate: false - xy: 1827, 417 + xy: 1675, 930 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conduit-bridge rotate: false - xy: 1827, 383 + xy: 1709, 930 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conduit-end rotate: false - xy: 1861, 417 + xy: 1743, 930 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-0 rotate: false - xy: 1929, 349 + xy: 1285, 894 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-1 rotate: false - xy: 1963, 349 + xy: 1319, 894 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-2 rotate: false - xy: 1997, 349 + xy: 1353, 894 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-3 rotate: false - xy: 1063, 375 + xy: 1387, 909 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-4 rotate: false - xy: 1063, 341 + xy: 1421, 909 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-5 rotate: false - xy: 1097, 375 + xy: 1455, 909 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-6 rotate: false - xy: 1063, 307 + xy: 1489, 917 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 rotary-pump rotate: false - xy: 1139, 1046 + xy: 253, 1135 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 thermal-pump rotate: false - xy: 1041, 1299 + xy: 131, 613 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 alpha-dart-mech-pad rotate: false - xy: 1409, 1429 + xy: 919, 1397 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 delta-mech-pad rotate: false - xy: 667, 1005 + xy: 1183, 1429 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 glaive-ship-pad rotate: false - xy: 747, 1463 + xy: 807, 1463 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 javelin-ship-pad rotate: false - xy: 583, 473 + xy: 1909, 1429 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 omega-mech-pad rotate: false - xy: 1749, 1495 + xy: 1787, 1495 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 tau-mech-pad rotate: false - xy: 977, 905 + xy: 327, 1234 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 trident-ship-pad rotate: false - xy: 969, 839 + xy: 319, 1036 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 battery rotate: false - xy: 1173, 578 + xy: 1409, 1147 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 battery-large rotate: false - xy: 1063, 1593 + xy: 219, 1443 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 combustion-generator rotate: false - xy: 1377, 658 + xy: 1789, 1168 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 combustion-generator-top rotate: false - xy: 1377, 624 + xy: 1823, 1168 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 +differential-generator + rotate: false + xy: 1675, 1691 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +differential-generator-top + rotate: false + xy: 1773, 1691 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 impact-reactor rotate: false - xy: 1306, 1821 + xy: 1102, 1919 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 impact-reactor-bottom rotate: false - xy: 1436, 1821 + xy: 1232, 1919 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 impact-reactor-light rotate: false - xy: 1696, 1821 + xy: 1492, 1919 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 impact-reactor-plasma-0 rotate: false - xy: 1826, 1821 + xy: 1622, 1919 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 impact-reactor-plasma-1 rotate: false - xy: 509, 767 + xy: 1752, 1919 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 impact-reactor-plasma-2 rotate: false - xy: 509, 637 + xy: 1882, 1919 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 impact-reactor-plasma-3 rotate: false - xy: 453, 507 + xy: 526, 1789 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 impact-reactor-top rotate: false - xy: 526, 1691 + xy: 656, 1789 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 power-node rotate: false - xy: 1691, 349 + xy: 1151, 787 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 power-node-large rotate: false - xy: 1225, 1218 + xy: 1909, 1297 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 power-source rotate: false - xy: 1759, 349 + xy: 1251, 929 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 power-void rotate: false - xy: 1793, 349 + xy: 1285, 928 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 powerinfinite rotate: false - xy: 1827, 349 + xy: 1319, 928 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 powervoid rotate: false - xy: 1861, 349 + xy: 1353, 928 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 rtg-generator rotate: false - xy: 1129, 980 + xy: 253, 1069 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 rtg-generator-top rotate: false - xy: 1233, 340 + xy: 1795, 896 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 solar-panel rotate: false - xy: 1471, 349 + xy: 1897, 853 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 solar-panel-large rotate: false - xy: 943, 1201 + xy: 155, 711 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 surge-tower rotate: false - xy: 445, 243 + xy: 261, 1236 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 thermal-generator rotate: false - xy: 1043, 905 + xy: 393, 1234 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 thorium-reactor rotate: false - xy: 1139, 1397 + xy: 131, 515 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 thorium-reactor-center rotate: false - xy: 943, 1103 + xy: 131, 417 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 thorium-reactor-lights rotate: false - xy: 1041, 1201 + xy: 131, 319 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 turbine-generator rotate: false - xy: 903, 773 + xy: 385, 1102 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 turbine-generator-top rotate: false - xy: 1035, 839 + xy: 451, 1168 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 alloy-smelter rotate: false - xy: 867, 1593 + xy: 219, 1541 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 alloy-smelter-top rotate: false - xy: 965, 1593 + xy: 1087, 1691 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 blast-mixer rotate: false - xy: 1139, 1112 + xy: 1983, 1779 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cryofluidmixer-bottom rotate: false - xy: 1607, 1429 + xy: 229, 513 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cryofluidmixer-liquid rotate: false - xy: 1739, 1429 + xy: 229, 381 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cryofluidmixer-top rotate: false - xy: 1805, 1429 + xy: 229, 315 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cultivator rotate: false - xy: 1871, 1429 + xy: 229, 249 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cultivator-middle rotate: false - xy: 1956, 1671 + xy: 229, 117 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cultivator-top rotate: false - xy: 1945, 1605 + xy: 229, 51 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 graphite-press rotate: false - xy: 1063, 1037 + xy: 1843, 1429 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 incinerator rotate: false - xy: 1807, 485 + xy: 1539, 1032 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-source rotate: false - xy: 1977, 485 + xy: 1743, 998 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-void rotate: false - xy: 1671, 451 + xy: 1845, 998 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 kiln rotate: false - xy: 865, 971 + xy: 1051, 1347 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 kiln-top rotate: false - xy: 931, 971 + xy: 1117, 1363 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 silicon-smelter-top rotate: false - xy: 931, 971 + xy: 1117, 1363 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 lavasmelter rotate: false - xy: 1909, 451 + xy: 2015, 1015 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-source rotate: false - xy: 1987, 1063 + xy: 1709, 964 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 melter rotate: false - xy: 673, 13 + xy: 1947, 947 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 multi-press rotate: false - xy: 1161, 1495 + xy: 1493, 1495 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 phase-weaver rotate: false - xy: 681, 543 + xy: 1249, 1297 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 phase-weaver-bottom rotate: false - xy: 747, 609 + xy: 1315, 1297 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 phase-weaver-weave rotate: false - xy: 715, 477 + xy: 1447, 1297 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 plastanium-compressor rotate: false - xy: 781, 477 + xy: 1513, 1297 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 plastanium-compressor-top rotate: false - xy: 1335, 1355 + xy: 1579, 1297 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 pulverizer rotate: false - xy: 1097, 341 + xy: 1387, 875 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulverizer-rotator rotate: false - xy: 1097, 307 + xy: 1455, 875 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pyratite-mixer rotate: false - xy: 1213, 1152 + xy: 1975, 1251 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 separator rotate: false - xy: 1467, 1363 + xy: 1579, 1231 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 separator-liquid rotate: false - xy: 1533, 1363 + xy: 1645, 1231 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 silicon-smelter rotate: false - xy: 1599, 1363 + xy: 1711, 1231 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 smelter rotate: false - xy: 1369, 250 + xy: 1863, 853 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 spore-press rotate: false - xy: 1929, 1341 + xy: 1975, 1185 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spore-press-frame0 rotate: false - xy: 1435, 1289 + xy: 319, 1368 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spore-press-frame1 rotate: false - xy: 1501, 1297 + xy: 385, 1366 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spore-press-frame2 rotate: false - xy: 1567, 1297 + xy: 451, 1366 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spore-press-liquid rotate: false - xy: 1699, 1297 + xy: 583, 1350 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spore-press-top rotate: false - xy: 1765, 1297 + xy: 261, 1302 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 container rotate: false - xy: 1475, 1429 + xy: 1983, 1647 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 core-foundation rotate: false - xy: 1176, 1821 + xy: 972, 1919 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 core-nucleus rotate: false - xy: 291, 493 + xy: 1, 1235 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 core-shard rotate: false - xy: 1259, 1593 + xy: 1283, 1691 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 core-shard-top rotate: false - xy: 1357, 1593 + xy: 1381, 1691 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 launch-pad rotate: false - xy: 649, 1169 + xy: 1101, 1495 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 sortedunloader rotate: false - xy: 1471, 315 + xy: 1965, 879 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 unloader rotate: false - xy: 1071, 171 + xy: 495, 182 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 vault rotate: false - xy: 1041, 1103 + xy: 131, 25 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 arc-heat rotate: false - xy: 1207, 612 + xy: 2012, 1921 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-1 rotate: false - xy: 1241, 578 + xy: 1477, 1155 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-2 rotate: false - xy: 1956, 1737 + xy: 1983, 1713 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-3 rotate: false - xy: 1161, 1593 + xy: 1185, 1691 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-4 rotate: false - xy: 656, 1821 + xy: 323, 1628 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 hail-heat rotate: false - xy: 581, 897 + xy: 526, 1919 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 lancer-heat rotate: false - xy: 1063, 971 + xy: 1249, 1363 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 meltdown-heat rotate: false - xy: 786, 1691 + xy: 916, 1789 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 ripple-heat rotate: false - xy: 845, 1299 + xy: 163, 1299 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 salvo-heat rotate: false - xy: 1291, 1218 + xy: 919, 1331 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 salvo-panel-left rotate: false - xy: 1271, 1086 + xy: 1051, 1281 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 salvo-panel-right rotate: false - xy: 1271, 1020 + xy: 1117, 1231 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 wave-liquid rotate: false - xy: 1011, 575 + xy: 385, 838 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +crawler-factory + rotate: false + xy: 1983, 1515 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 dagger-factory rotate: false - xy: 1945, 1539 + xy: 1983, 1515 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 phantom-factory rotate: false - xy: 1945, 1539 + xy: 1983, 1515 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spirit-factory rotate: false - xy: 1945, 1539 + xy: 1983, 1515 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 wraith-factory rotate: false - xy: 1945, 1539 + xy: 1983, 1515 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +crawler-factory-top + rotate: false + xy: 229, 645 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +crawler-factory-top-open + rotate: false + xy: 229, 579 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 dagger-factory-top rotate: false - xy: 535, 1005 + xy: 1051, 1413 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 dagger-factory-top-open rotate: false - xy: 601, 1005 + xy: 1117, 1429 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 fortress-factory rotate: false - xy: 453, 1116 + xy: 1871, 1691 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 fortress-factory-top rotate: false - xy: 291, 13 + xy: 513, 1432 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 ghoul-factory-top rotate: false - xy: 291, 13 + xy: 513, 1432 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 titan-factory-top rotate: false - xy: 291, 13 + xy: 513, 1432 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 fortress-factory-top-open rotate: false - xy: 583, 539 + xy: 611, 1561 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 ghoul-factory-top-open rotate: false - xy: 583, 539 + xy: 611, 1561 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 titan-factory-top-open rotate: false - xy: 583, 539 + xy: 611, 1561 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 ghoul-factory rotate: false - xy: 649, 1463 + xy: 709, 1463 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 phantom-factory-top rotate: false - xy: 705, 675 + xy: 1975, 1317 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 phantom-factory-top-open rotate: false - xy: 771, 675 + xy: 1117, 1297 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 repair-point-base rotate: false - xy: 1165, 374 + xy: 1557, 896 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 revenant-factory rotate: false - xy: 1046, 1691 + xy: 1176, 1789 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 revenant-factory-top rotate: false - xy: 1306, 1691 + xy: 1436, 1789 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 revenant-factory-top-open rotate: false - xy: 1436, 1691 + xy: 1566, 1789 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 spirit-factory-top rotate: false - xy: 1797, 1363 + xy: 1843, 1231 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spirit-factory-top-open rotate: false - xy: 1863, 1363 + xy: 1909, 1231 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 titan-factory rotate: false - xy: 1139, 1299 + xy: 131, 221 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 wraith-factory-top rotate: false - xy: 979, 509 + xy: 385, 772 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 wraith-factory-top-open rotate: false - xy: 913, 443 + xy: 451, 838 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 copper-wall rotate: false - xy: 1433, 553 + xy: 1919, 1057 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 copper-wall-large rotate: false - xy: 1541, 1429 + xy: 1983, 1581 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 door rotate: false - xy: 1603, 477 + xy: 1167, 897 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 door-large rotate: false - xy: 581, 939 + xy: 1315, 1429 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 door-large-open rotate: false - xy: 647, 939 + xy: 1381, 1429 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 door-open rotate: false - xy: 1637, 511 + xy: 1267, 997 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-wall rotate: false - xy: 1929, 383 + xy: 1913, 921 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-wall-large rotate: false - xy: 681, 609 + xy: 1183, 1297 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 scrap-wall-gigantic rotate: false - xy: 1696, 1691 + xy: 1826, 1789 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 scrap-wall-huge1 rotate: false - xy: 943, 1299 + xy: 155, 1005 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 scrap-wall-huge2 rotate: false - xy: 1041, 1397 + xy: 155, 907 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 scrap-wall-huge3 rotate: false - xy: 845, 1103 + xy: 155, 809 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 scrap-wall-large1 rotate: false - xy: 1261, 954 + xy: 1315, 1231 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 scrap-wall-large2 rotate: false - xy: 1261, 888 + xy: 1381, 1231 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 scrap-wall-large3 rotate: false - xy: 1369, 1289 + xy: 1447, 1231 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 scrap-wall-large4 rotate: false - xy: 1401, 1355 + xy: 1513, 1231 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 scrap-wall1 rotate: false - xy: 1267, 297 + xy: 1557, 862 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scrap-wall2 rotate: false - xy: 1301, 331 + xy: 1591, 862 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scrap-wall3 rotate: false - xy: 1301, 297 + xy: 1625, 862 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scrap-wall4 rotate: false - xy: 1267, 263 + xy: 1659, 862 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scrap-wall5 rotate: false - xy: 1267, 263 + xy: 1659, 862 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 surge-wall rotate: false - xy: 1709, 281 + xy: 1659, 828 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 surge-wall-large rotate: false - xy: 487, 177 + xy: 327, 1300 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 thorium-wall rotate: false - xy: 1811, 247 + xy: 1897, 819 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 thorium-wall-large rotate: false - xy: 837, 839 + xy: 459, 1234 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 thruster rotate: false - xy: 607, 1561 + xy: 713, 1659 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 titanium-wall rotate: false - xy: 1947, 213 + xy: 495, 352 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-wall-large rotate: false - xy: 837, 707 + xy: 385, 1168 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 bullet rotate: false - xy: 1995, 1353 + xy: 295, 660 size: 52, 52 orig: 52, 52 offset: 0, 0 index: -1 bullet-back rotate: false - xy: 1995, 1299 + xy: 295, 606 size: 52, 52 orig: 52, 52 offset: 0, 0 index: -1 casing rotate: false - xy: 1129, 1085 + xy: 1041, 1313 size: 8, 16 orig: 8, 16 offset: 0, 0 index: -1 error rotate: false - xy: 1395, 1134 + xy: 575, 1028 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 laser rotate: false - xy: 545, 1511 + xy: 2041, 1399 size: 4, 48 orig: 4, 48 offset: 0, 0 index: -1 laser-end rotate: false - xy: 1335, 1421 + xy: 697, 1389 size: 72, 72 orig: 72, 72 offset: 0, 0 index: -1 minelaser rotate: false - xy: 2043, 907 + xy: 2041, 1349 size: 4, 48 orig: 4, 48 offset: 0, 0 index: -1 minelaser-end rotate: false - xy: 1139, 1178 + xy: 771, 1389 size: 72, 72 orig: 72, 72 offset: 0, 0 index: -1 missile rotate: false - xy: 1135, 629 + xy: 1893, 1193 size: 36, 36 orig: 36, 36 offset: 0, 0 index: -1 missile-back rotate: false - xy: 1135, 591 + xy: 1931, 1193 size: 36, 36 orig: 36, 36 offset: 0, 0 index: -1 scale_marker rotate: false - xy: 421, 111 + xy: 317, 1633 size: 4, 4 orig: 4, 4 offset: 0, 0 index: -1 scorch1 rotate: false - xy: 1081, 1 + xy: 1219, 811 size: 28, 100 orig: 28, 100 offset: 0, 0 index: -1 scorch2 rotate: false - xy: 1111, 28 + xy: 1249, 793 size: 28, 100 orig: 28, 100 offset: 0, 0 index: -1 scorch3 rotate: false - xy: 1230, 136 + xy: 1279, 792 size: 28, 100 orig: 28, 100 offset: 0, 0 index: -1 scorch4 rotate: false - xy: 1260, 136 + xy: 1309, 792 size: 28, 100 orig: 28, 100 offset: 0, 0 index: -1 scorch5 rotate: false - xy: 1290, 161 + xy: 1339, 792 size: 28, 100 orig: 28, 100 offset: 0, 0 index: -1 shell rotate: false - xy: 1907, 1303 + xy: 1363, 1059 size: 36, 36 orig: 36, 36 offset: 0, 0 index: -1 shell-back rotate: false - xy: 2001, 675 + xy: 1317, 1030 size: 36, 36 orig: 36, 36 offset: 0, 0 index: -1 shot rotate: false - xy: 1369, 284 + xy: 1863, 887 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 transfer rotate: false - xy: 2043, 857 + xy: 2041, 1299 size: 4, 48 orig: 4, 48 offset: 0, 0 index: -1 transfer-arrow rotate: false - xy: 2015, 213 + xy: 495, 284 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 transfer-end rotate: false - xy: 1956, 1803 + xy: 845, 1389 size: 72, 72 orig: 72, 72 offset: 0, 0 index: -1 alloy-smelter-icon-large rotate: false - xy: 477, 1511 + xy: 229, 1 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 alloy-smelter-icon-medium rotate: false - xy: 1173, 646 + xy: 691, 1205 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 alloy-smelter-icon-small rotate: false - xy: 1451, 850 + xy: 1091, 1255 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 alpha-dart-mech-pad-icon-large rotate: false - xy: 511, 341 + xy: 279, 1 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 alpha-dart-mech-pad-icon-medium rotate: false - xy: 1173, 612 + xy: 2012, 1989 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 alpha-dart-mech-pad-icon-small rotate: false - xy: 1551, 813 + xy: 583, 1633 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 arc rotate: false - xy: 1207, 646 + xy: 2012, 1955 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 arc-icon-full rotate: false - xy: 1298, 671 + xy: 1074, 734 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 arc-icon-large rotate: false - xy: 561, 315 + xy: 295, 506 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 arc-icon-small rotate: false - xy: 1003, 77 + xy: 1956, 1819 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 battery-icon-large rotate: false - xy: 561, 265 + xy: 295, 398 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 battery-icon-small rotate: false - xy: 879, 549 + xy: 891, 1363 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 battery-large-icon-large rotate: false - xy: 611, 257 + xy: 295, 348 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 battery-large-icon-medium rotate: false - xy: 1207, 578 + xy: 1409, 1113 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 battery-large-icon-small rotate: false - xy: 1945, 1103 + xy: 499, 552 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 blast-drill-icon-full rotate: false - xy: 291, 111 + xy: 1, 471 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 blast-drill-icon-large rotate: false - xy: 693, 423 + xy: 295, 298 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 blast-drill-icon-medium rotate: false - xy: 1241, 646 + xy: 1443, 1155 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 blast-drill-icon-small rotate: false - xy: 775, 89 + xy: 1219, 747 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 blast-mixer-icon-large rotate: false - xy: 743, 427 + xy: 295, 248 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 blast-mixer-icon-medium rotate: false - xy: 1241, 612 + xy: 1443, 1121 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 blast-mixer-icon-small rotate: false - xy: 1111, 2 + xy: 1398, 849 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 bridge-conduit-icon-large rotate: false - xy: 553, 215 + xy: 295, 98 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 bridge-conduit-icon-small rotate: false - xy: 1349, 224 + xy: 1398, 823 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 bridge-conveyor-icon-large rotate: false - xy: 553, 165 + xy: 399, 664 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 bridge-conveyor-icon-small rotate: false - xy: 1320, 161 + xy: 1956, 1793 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 char-icon-large rotate: false - xy: 603, 157 + xy: 435, 722 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 char-icon-small rotate: false - xy: 1375, 224 + xy: 499, 526 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 cliffs-icon-large rotate: false - xy: 677, 365 + xy: 449, 672 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 cliffs-icon-small rotate: false - xy: 1349, 198 + xy: 1424, 849 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 combustion-generator-icon-large rotate: false - xy: 661, 315 + xy: 449, 622 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 combustion-generator-icon-small rotate: false - xy: 1375, 198 + xy: 1424, 823 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 conduit-icon-full rotate: false - xy: 1547, 613 + xy: 1647, 1100 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-icon-large rotate: false - xy: 661, 265 + xy: 641, 1300 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 conduit-icon-small rotate: false - xy: 1401, 221 + xy: 1450, 849 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 container-icon-large rotate: false - xy: 711, 315 + xy: 641, 1250 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 container-icon-medium rotate: false - xy: 1581, 579 + xy: 1817, 1134 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 container-icon-small rotate: false - xy: 1427, 221 + xy: 1450, 823 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 conveyor-icon-large rotate: false - xy: 711, 265 + xy: 641, 1200 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 conveyor-icon-small rotate: false - xy: 1453, 221 + xy: 533, 704 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 copper-wall-icon-large rotate: false - xy: 1357, 1234 + xy: 349, 564 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 copper-wall-icon-small rotate: false - xy: 1479, 221 + xy: 1369, 786 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 copper-wall-large-icon-large rotate: false - xy: 1407, 1239 + xy: 399, 564 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 copper-wall-large-icon-medium rotate: false - xy: 1467, 553 + xy: 1401, 1045 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 copper-wall-large-icon-small rotate: false - xy: 1136, 134 + xy: 1248, 767 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 core-foundation-icon-large rotate: false - xy: 1457, 1239 + xy: 449, 572 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 core-foundation-icon-medium rotate: false - xy: 1501, 553 + xy: 1959, 1151 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 core-foundation-icon-small rotate: false - xy: 1401, 195 + xy: 1274, 766 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 core-nucleus-icon-large rotate: false - xy: 1507, 1247 + xy: 345, 514 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 core-nucleus-icon-medium rotate: false - xy: 1433, 519 + xy: 1993, 1151 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 core-nucleus-icon-small rotate: false - xy: 1427, 195 + xy: 1300, 766 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 core-shard-icon-large rotate: false - xy: 1557, 1247 + xy: 345, 464 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 core-shard-icon-medium rotate: false - xy: 1467, 519 + xy: 1953, 1117 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 core-shard-icon-small rotate: false - xy: 1453, 195 + xy: 1326, 766 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 craters-icon-large rotate: false - xy: 1607, 1247 + xy: 395, 514 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 craters-icon-small rotate: false - xy: 1479, 195 + xy: 1245, 741 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +crawler-factory-icon-full + rotate: false + xy: 1983, 1449 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +crawler-factory-icon-large + rotate: false + xy: 345, 364 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +crawler-factory-icon-medium + rotate: false + xy: 1953, 1083 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +crawler-factory-icon-small + rotate: false + xy: 1271, 740 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 cryofluidmixer-icon-full rotate: false - xy: 1673, 1429 + xy: 229, 447 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cryofluidmixer-icon-large rotate: false - xy: 1807, 1247 + xy: 345, 314 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 cryofluidmixer-icon-medium rotate: false - xy: 1603, 511 + xy: 1987, 1117 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cryofluidmixer-icon-small rotate: false - xy: 1505, 213 + xy: 1297, 740 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 cultivator-icon-full rotate: false - xy: 1237, 1284 + xy: 229, 183 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cultivator-icon-large rotate: false - xy: 1857, 1247 + xy: 395, 364 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 cultivator-icon-medium rotate: false - xy: 1365, 488 + xy: 1987, 1083 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cultivator-icon-small rotate: false - xy: 1531, 213 + xy: 1323, 740 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 cyclone rotate: false - xy: 1455, 1593 + xy: 1479, 1691 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 cyclone-icon-full rotate: false - xy: 1553, 1593 + xy: 1577, 1691 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 cyclone-icon-large rotate: false - xy: 1357, 1184 + xy: 345, 264 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 cyclone-icon-medium rotate: false - xy: 1399, 488 + xy: 1953, 1049 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cyclone-icon-small rotate: false - xy: 1557, 213 + xy: 1476, 823 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 dagger-factory-icon-full rotate: false - xy: 1945, 1473 + xy: 985, 1397 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 dagger-factory-icon-large rotate: false - xy: 1507, 1197 + xy: 395, 264 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 dagger-factory-icon-medium rotate: false - xy: 1433, 485 + xy: 1987, 1049 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 dagger-factory-icon-small rotate: false - xy: 1583, 213 + xy: 1398, 797 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -deepwater-edge - rotate: false - xy: 1, 897 - size: 288, 96 - orig: 288, 96 - offset: 0, 0 - index: -1 deepwater-icon-large rotate: false - xy: 1657, 1197 + xy: 345, 114 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 deepwater-icon-small rotate: false - xy: 1609, 213 + xy: 1424, 797 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 delta-mech-pad-icon-large rotate: false - xy: 1857, 1197 + xy: 395, 64 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 delta-mech-pad-icon-medium rotate: false - xy: 1501, 485 + xy: 1117, 847 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 delta-mech-pad-icon-small rotate: false - xy: 1505, 187 + xy: 1450, 797 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 differential-generator-icon-large rotate: false - xy: 1345, 1134 + xy: 329, 14 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 differential-generator-icon-medium rotate: false - xy: 1535, 477 + xy: 1117, 813 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 differential-generator-icon-small rotate: false - xy: 1531, 187 + xy: 1476, 797 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 distributor-icon-large rotate: false - xy: 1337, 1084 + xy: 379, 14 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 distributor-icon-medium rotate: false - xy: 1569, 477 + xy: 1117, 779 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 distributor-icon-small rotate: false - xy: 1557, 187 + xy: 1244, 715 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 door-icon-large rotate: false - xy: 1337, 1034 + xy: 429, 14 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 door-icon-small rotate: false - xy: 1583, 187 + xy: 1244, 689 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 door-large-icon-large rotate: false - xy: 1337, 984 + xy: 575, 1178 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 door-large-icon-medium rotate: false - xy: 1637, 545 + xy: 1217, 947 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 door-large-icon-small rotate: false - xy: 1609, 187 + xy: 1244, 663 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 dunerocks-icon-large rotate: false - xy: 1327, 934 + xy: 575, 1128 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 dunerocks-icon-small rotate: false - xy: 1635, 187 + xy: 1270, 714 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 duo rotate: false - xy: 1685, 621 + xy: 1301, 996 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 duo-icon-full rotate: false - xy: 1719, 621 + xy: 1335, 996 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 duo-icon-large rotate: false - xy: 1327, 884 + xy: 575, 1078 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 duo-icon-small rotate: false - xy: 1661, 187 + xy: 1270, 688 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 force-projector-icon-large rotate: false - xy: 777, 377 + xy: 575, 812 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 force-projector-icon-medium rotate: false - xy: 1787, 621 + xy: 1403, 1011 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 force-projector-icon-small rotate: false - xy: 1687, 187 + xy: 1296, 714 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 fortress-factory-icon-full rotate: false - xy: 437, 1018 + xy: 513, 1530 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 fortress-factory-icon-large rotate: false - xy: 827, 377 + xy: 574, 762 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 fortress-factory-icon-medium rotate: false - xy: 1821, 621 + xy: 1403, 977 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 fortress-factory-icon-small rotate: false - xy: 1713, 187 + xy: 1296, 688 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 fuse rotate: false - xy: 551, 1463 + xy: 611, 1463 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 fuse-icon-full rotate: false - xy: 551, 1365 + xy: 709, 1561 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 fuse-icon-large rotate: false - xy: 1445, 1139 + xy: 625, 1150 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 fuse-icon-medium rotate: false - xy: 1855, 621 + xy: 1435, 1045 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 fuse-icon-small rotate: false - xy: 1739, 187 + xy: 1322, 714 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 ghoul-factory-icon-full rotate: false - xy: 551, 1267 + xy: 807, 1561 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 ghoul-factory-icon-large rotate: false - xy: 1387, 976 + xy: 625, 1100 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 ghoul-factory-icon-medium rotate: false - xy: 1889, 621 + xy: 1437, 1011 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ghoul-factory-icon-small rotate: false - xy: 1765, 187 + xy: 1322, 688 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 glaive-ship-pad-icon-large rotate: false - xy: 1377, 926 + xy: 625, 1050 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 glaive-ship-pad-icon-medium rotate: false - xy: 1923, 621 + xy: 1437, 977 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 glaive-ship-pad-icon-small rotate: false - xy: 1791, 187 + xy: 1270, 662 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 graphite-press-icon-large rotate: false - xy: 1377, 876 + xy: 625, 1000 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 graphite-press-icon-medium rotate: false - xy: 1649, 587 + xy: 1469, 1053 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 graphite-press-icon-small rotate: false - xy: 1817, 187 + xy: 1296, 662 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +grass-icon-large + rotate: false + xy: 625, 950 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +grass-icon-small + rotate: false + xy: 1322, 662 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 hail rotate: false - xy: 1785, 587 + xy: 1503, 1053 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 hail-icon-full rotate: false - xy: 1819, 587 + xy: 1471, 1019 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 hail-icon-large rotate: false - xy: 761, 315 + xy: 625, 900 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 hail-icon-small rotate: false - xy: 1843, 187 + xy: 77, 8 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -holostone-edge - rotate: false - xy: 1, 603 - size: 288, 96 - orig: 288, 96 - offset: 0, 0 - index: -1 holostone-icon-large rotate: false - xy: 811, 327 + xy: 625, 800 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 holostone-icon-small rotate: false - xy: 1869, 187 + xy: 103, 11 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 hotrock-icon-large rotate: false - xy: 811, 277 + xy: 624, 750 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 hotrock-icon-small rotate: false - xy: 1895, 187 + xy: 533, 678 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 ice-icon-large rotate: false - xy: 877, 377 + xy: 675, 1150 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 ice-icon-small rotate: false - xy: 1921, 187 + xy: 530, 652 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -ice-snow-edge - rotate: false - xy: 1, 407 - size: 288, 96 - orig: 288, 96 - offset: 0, 0 - index: -1 ice-snow-icon-large rotate: false - xy: 861, 327 + xy: 675, 1100 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 ice-snow-icon-small rotate: false - xy: 1947, 187 + xy: 530, 626 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 icerocks-icon-large rotate: false - xy: 861, 277 + xy: 675, 1050 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 icerocks-icon-small rotate: false - xy: 1973, 187 + xy: 530, 600 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 ignarock-icon-large rotate: false - xy: 911, 327 + xy: 675, 950 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 ignarock-icon-small rotate: false - xy: 1141, 56 + xy: 529, 496 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 impact-reactor-icon-full rotate: false - xy: 1566, 1821 + xy: 1362, 1919 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 impact-reactor-icon-large rotate: false - xy: 911, 277 + xy: 675, 900 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 impact-reactor-icon-medium rotate: false - xy: 1841, 553 + xy: 1505, 985 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 impact-reactor-icon-small rotate: false - xy: 1141, 30 + xy: 529, 470 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 incinerator-icon-large rotate: false - xy: 1495, 1139 + xy: 675, 850 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 incinerator-icon-small rotate: false - xy: 1319, 109 + xy: 529, 444 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-blast-compound-medium rotate: false - xy: 1349, 172 + xy: 529, 376 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-blast-compound-small rotate: false - xy: 509, 1000 + xy: 2030, 1903 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-blast-compound-xlarge rotate: false - xy: 2007, 1257 + xy: 649, 1374 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-coal-medium rotate: false - xy: 1375, 172 + xy: 529, 350 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-coal-small rotate: false - xy: 681, 121 + xy: 2030, 1885 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-coal-xlarge rotate: false - xy: 511, 249 + xy: 219, 1401 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-copper-medium rotate: false - xy: 1401, 169 + xy: 529, 324 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-copper-small rotate: false - xy: 2025, 657 + xy: 2030, 1867 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-copper-xlarge rotate: false - xy: 2007, 1215 + xy: 261, 1401 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-graphite-medium rotate: false - xy: 1427, 169 + xy: 529, 298 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-graphite-small rotate: false - xy: 527, 1507 + xy: 2030, 1849 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-graphite-xlarge rotate: false - xy: 477, 1716 + xy: 1325, 1139 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-lead-medium rotate: false - xy: 1453, 169 + xy: 529, 272 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-lead-small rotate: false - xy: 1193, 116 + xy: 2027, 1167 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-lead-xlarge rotate: false - xy: 1101, 713 + xy: 1425, 1189 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-metaglass-medium rotate: false - xy: 1479, 169 + xy: 529, 246 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-metaglass-small rotate: false - xy: 1193, 98 + xy: 1858, 801 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-metaglass-xlarge rotate: false - xy: 1651, 655 + xy: 1075, 839 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-phase-fabric-medium rotate: false - xy: 1505, 161 + xy: 529, 220 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-phase-fabric-small rotate: false - xy: 1193, 80 + xy: 1876, 801 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-phase-fabric-xlarge rotate: false - xy: 1951, 1199 + xy: 1125, 889 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-plastanium-medium rotate: false - xy: 1531, 161 + xy: 529, 194 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-plastanium-small rotate: false - xy: 1193, 62 + xy: 1858, 783 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-plastanium-xlarge rotate: false - xy: 1693, 655 + xy: 1175, 939 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-pyratite-medium rotate: false - xy: 1557, 161 + xy: 529, 168 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-pyratite-small rotate: false - xy: 1193, 44 + xy: 1894, 801 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-pyratite-xlarge rotate: false - xy: 1735, 655 + xy: 1225, 989 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-sand-medium rotate: false - xy: 1583, 161 + xy: 529, 142 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-sand-small rotate: false - xy: 1206, 134 + xy: 1876, 783 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-sand-xlarge rotate: false - xy: 1777, 655 + xy: 1275, 1039 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-scrap-medium rotate: false - xy: 1609, 161 + xy: 529, 116 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-scrap-small rotate: false - xy: 1211, 116 + xy: 1912, 801 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-scrap-xlarge rotate: false - xy: 1819, 655 + xy: 1325, 1097 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-silicon-medium rotate: false - xy: 1635, 161 + xy: 529, 90 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-silicon-small rotate: false - xy: 1211, 98 + xy: 1894, 783 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-silicon-xlarge rotate: false - xy: 1861, 655 + xy: 1367, 1139 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-source-icon-large rotate: false - xy: 1545, 1147 + xy: 675, 800 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 item-source-icon-small rotate: false - xy: 1661, 161 + xy: 529, 64 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-spore-pod-medium rotate: false - xy: 1687, 161 + xy: 529, 38 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-spore-pod-small rotate: false - xy: 1211, 80 + xy: 1912, 783 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-spore-pod-xlarge rotate: false - xy: 1903, 655 + xy: 1467, 1189 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-surge-alloy-medium rotate: false - xy: 1713, 161 + xy: 529, 12 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-surge-alloy-small rotate: false - xy: 1211, 62 + xy: 1930, 793 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-surge-alloy-xlarge rotate: false - xy: 1945, 655 + xy: 1075, 797 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-thorium-medium rotate: false - xy: 1739, 161 + xy: 1395, 771 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-thorium-small rotate: false - xy: 1211, 44 + xy: 1948, 793 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-thorium-xlarge rotate: false - xy: 389, 3 + xy: 1367, 1097 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-titanium-medium rotate: false - xy: 1765, 161 + xy: 1421, 771 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-titanium-small rotate: false - xy: 1229, 118 + xy: 1966, 793 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-titanium-xlarge rotate: false - xy: 537, 123 + xy: 1509, 1189 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 item-void-icon-large rotate: false - xy: 1595, 1147 + xy: 674, 750 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 item-void-icon-small rotate: false - xy: 1791, 161 + xy: 1447, 771 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 javelin-ship-pad-icon-large rotate: false - xy: 1695, 1147 + xy: 445, 472 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 javelin-ship-pad-icon-medium rotate: false - xy: 1705, 451 + xy: 1879, 1023 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 javelin-ship-pad-icon-small rotate: false - xy: 1817, 161 + xy: 1473, 771 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 junction-icon-large rotate: false - xy: 1795, 1147 + xy: 445, 372 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 junction-icon-small rotate: false - xy: 1843, 161 + xy: 2021, 1125 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 kiln-icon-large rotate: false - xy: 1845, 1147 + xy: 445, 322 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 kiln-icon-medium rotate: false - xy: 1773, 451 + xy: 1879, 989 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 kiln-icon-small rotate: false - xy: 1869, 161 + xy: 2021, 1099 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 lancer rotate: false - xy: 997, 971 + xy: 1183, 1363 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 lancer-icon-full rotate: false - xy: 649, 473 + xy: 1315, 1363 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 lancer-icon-large rotate: false - xy: 811, 227 + xy: 445, 272 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 lancer-icon-medium rotate: false - xy: 1807, 451 + xy: 1913, 989 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 lancer-icon-small rotate: false - xy: 1895, 161 + xy: 2021, 1073 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 laser-drill-icon-full rotate: false - xy: 551, 1169 + xy: 905, 1463 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 laser-drill-icon-large rotate: false - xy: 861, 227 + xy: 445, 222 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 laser-drill-icon-medium rotate: false - xy: 1841, 451 + xy: 1947, 1015 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 laser-drill-icon-small rotate: false - xy: 1921, 161 + xy: 553, 736 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 launch-pad-icon-large rotate: false - xy: 911, 227 + xy: 445, 172 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 launch-pad-icon-medium rotate: false - xy: 1875, 451 + xy: 1981, 1015 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 launch-pad-icon-small rotate: false - xy: 1947, 161 + xy: 579, 736 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 liquid-junction-icon-large rotate: false - xy: 1945, 1291 + xy: 445, 72 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 liquid-junction-icon-small rotate: false - xy: 1973, 161 + xy: 559, 710 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 liquid-router-icon-full rotate: false - xy: 2013, 1181 + xy: 1573, 964 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-router-icon-large rotate: false - xy: 1907, 1241 + xy: 479, 22 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 liquid-router-icon-small rotate: false - xy: 1999, 161 + xy: 559, 684 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 liquid-source-icon-large rotate: false - xy: 1957, 1241 + xy: 691, 1339 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 liquid-source-icon-small rotate: false - xy: 1162, 134 + xy: 585, 710 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 liquid-tank-icon-full rotate: false - xy: 551, 1071 + xy: 1199, 1495 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 liquid-tank-icon-large rotate: false - xy: 1427, 926 + xy: 691, 1289 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 liquid-tank-icon-medium rotate: false - xy: 1987, 1029 + xy: 1743, 964 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-tank-icon-small rotate: false - xy: 1167, 108 + xy: 585, 684 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 magmarock-icon-large rotate: false - xy: 1427, 876 + xy: 741, 1339 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 magmarock-icon-small rotate: false - xy: 1167, 82 + xy: 559, 658 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 mass-driver rotate: false - xy: 867, 1495 + xy: 1395, 1593 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 mass-driver-icon-full rotate: false - xy: 1063, 1495 + xy: 1493, 1593 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 mass-driver-icon-large rotate: false - xy: 1101, 855 + xy: 691, 1239 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 mass-driver-icon-medium rotate: false - xy: 707, 81 + xy: 1811, 964 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 mass-driver-icon-small rotate: false - xy: 1167, 56 + xy: 585, 658 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 mech-icon-alpha-mech rotate: false - xy: 1101, 805 + xy: 741, 1289 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 mech-icon-dart-ship rotate: false - xy: 1101, 755 + xy: 791, 1339 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 mech-icon-delta-mech rotate: false - xy: 1545, 1097 + xy: 741, 1239 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 mech-icon-glaive-ship rotate: false - xy: 519, 449 + xy: 583, 1234 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 mech-icon-javelin-ship rotate: false - xy: 1595, 1097 + xy: 791, 1289 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 mech-icon-omega-mech rotate: false - xy: 1045, 511 + xy: 517, 1170 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 mech-icon-tau-mech rotate: false - xy: 1103, 511 + xy: 517, 1112 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 mech-icon-trident-ship rotate: false - xy: 455, 59 + xy: 517, 1054 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 mechanical-drill-icon-full rotate: false - xy: 639, 807 + xy: 1447, 1363 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 mechanical-drill-icon-large rotate: false - xy: 1645, 1097 + xy: 841, 1339 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 mechanical-drill-icon-medium rotate: false - xy: 707, 47 + xy: 1845, 964 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 mechanical-drill-icon-small rotate: false - xy: 1167, 30 + xy: 556, 632 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 mechanical-pump-icon-large rotate: false - xy: 1695, 1097 + xy: 791, 1239 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 mechanical-pump-icon-small rotate: false - xy: 2021, 1087 + xy: 556, 606 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 meltdown rotate: false - xy: 656, 1691 + xy: 786, 1789 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 meltdown-icon-full rotate: false - xy: 916, 1691 + xy: 1046, 1789 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 meltdown-icon-large rotate: false - xy: 1745, 1097 + xy: 841, 1289 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 meltdown-icon-medium rotate: false - xy: 741, 47 + xy: 1913, 955 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 meltdown-icon-small rotate: false - xy: 2021, 1061 + xy: 582, 632 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 melter-icon-large rotate: false - xy: 1795, 1097 + xy: 841, 1239 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 melter-icon-small rotate: false - xy: 2021, 1035 + xy: 582, 606 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 mend-projector-icon-large rotate: false - xy: 1845, 1097 + xy: 891, 1281 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 mend-projector-icon-medium rotate: false - xy: 707, 13 + xy: 1981, 947 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 mend-projector-icon-small rotate: false - xy: 2021, 1009 + xy: 556, 580 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 metal-floor-2-icon-large rotate: false - xy: 1895, 1097 + xy: 941, 1281 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 metal-floor-2-icon-small rotate: false - xy: 2021, 983 + xy: 582, 580 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 metal-floor-3-icon-large rotate: false - xy: 653, 207 + xy: 991, 1281 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 metal-floor-3-icon-small rotate: false - xy: 2021, 957 + xy: 1502, 802 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 metal-floor-5-icon-large rotate: false - xy: 653, 157 + xy: 891, 1231 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 metal-floor-5-icon-small rotate: false - xy: 2022, 1777 + xy: 1528, 802 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 metal-floor-damaged-icon-large rotate: false - xy: 703, 215 + xy: 941, 1231 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 metal-floor-damaged-icon-small rotate: false - xy: 2022, 1751 + xy: 1554, 802 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -metal-floor-edge - rotate: false - xy: 1, 309 - size: 288, 96 - orig: 288, 96 - offset: 0, 0 - index: -1 metal-floor-icon-large rotate: false - xy: 703, 165 + xy: 991, 1231 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 metal-floor-icon-small rotate: false - xy: 2022, 1725 + xy: 1580, 802 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +moss-icon-large + rotate: false + xy: 1041, 1231 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +moss-icon-small + rotate: false + xy: 1606, 802 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 multi-press-icon-large rotate: false - xy: 753, 215 + xy: 725, 1189 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 multi-press-icon-medium rotate: false - xy: 843, 9 + xy: 2015, 947 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 multi-press-icon-small rotate: false - xy: 2022, 1699 + xy: 1632, 802 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 oil-extractor-icon-full rotate: false - xy: 1357, 1495 + xy: 1591, 1495 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 oil-extractor-icon-large rotate: false - xy: 753, 165 + xy: 725, 1139 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 oil-extractor-icon-medium rotate: false - xy: 877, 9 + xy: 1267, 963 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 oil-extractor-icon-small rotate: false - xy: 2022, 1673 + xy: 1658, 802 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 omega-mech-pad-icon-large rotate: false - xy: 803, 177 + xy: 775, 1189 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 omega-mech-pad-icon-medium rotate: false - xy: 911, 9 + xy: 1301, 962 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 omega-mech-pad-icon-small rotate: false - xy: 1346, 146 + xy: 1684, 802 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -ore-coal-holostone-icon-large +ore-coal-icon-full rotate: false - xy: 853, 177 + xy: 1335, 962 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-icon-medium + rotate: false + xy: 1335, 962 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal-icon-large + rotate: false + xy: 725, 1089 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -ore-coal-holostone-icon-small +ore-coal-icon-small rotate: false - xy: 1372, 146 + xy: 1710, 802 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -ore-coal-holostone1 +ore-copper-icon-full rotate: false - xy: 945, 9 + xy: 1369, 962 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-coal-holostone2 +ore-copper-icon-medium rotate: false - xy: 979, 43 + xy: 1369, 962 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-coal-holostone3 +ore-copper-icon-large rotate: false - xy: 979, 9 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-holostone-icon-full - rotate: false - xy: 979, 9 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-holostone-icon-medium - rotate: false - xy: 979, 9 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-sand-icon-large - rotate: false - xy: 903, 177 + xy: 775, 1139 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -ore-coal-sand-icon-small +ore-copper-icon-small rotate: false - xy: 1345, 120 + xy: 1736, 802 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -ore-coal-sand1 +ore-lead-icon-full rotate: false - xy: 1991, 641 + xy: 1403, 943 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-coal-sand2 +ore-lead-icon-medium rotate: false - xy: 977, 409 + xy: 1403, 943 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-coal-sand3 +ore-lead-icon-large rotate: false - xy: 1011, 410 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-sand-icon-full - rotate: false - xy: 1011, 410 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-sand-icon-medium - rotate: false - xy: 1011, 410 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-stained-stone-icon-large - rotate: false - xy: 803, 127 + xy: 825, 1189 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -ore-coal-stained-stone-icon-small +ore-lead-icon-small rotate: false - xy: 1371, 120 + xy: 1762, 802 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -ore-coal-stained-stone-red-icon-large +ore-scrap-icon-full rotate: false - xy: 853, 127 + xy: 1437, 943 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-icon-medium + rotate: false + xy: 1437, 943 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap-icon-large + rotate: false + xy: 725, 1039 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -ore-coal-stained-stone-red-icon-small +ore-scrap-icon-small rotate: false - xy: 1398, 143 + xy: 1788, 802 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -ore-coal-stained-stone-red1 +ore-thorium-icon-full rotate: false - xy: 961, 307 + xy: 1471, 951 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-coal-stained-stone-red2 +ore-thorium-icon-medium rotate: false - xy: 961, 273 + xy: 1471, 951 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-coal-stained-stone-red3 +ore-thorium-icon-large rotate: false - xy: 961, 239 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-stained-stone-red-icon-full - rotate: false - xy: 961, 239 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-stained-stone-red-icon-medium - rotate: false - xy: 961, 239 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-stained-stone1 - rotate: false - xy: 977, 375 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-stained-stone2 - rotate: false - xy: 1011, 376 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-stained-stone3 - rotate: false - xy: 961, 341 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-stained-stone-icon-full - rotate: false - xy: 961, 341 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-stained-stone-icon-medium - rotate: false - xy: 961, 341 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-stone-icon-large - rotate: false - xy: 903, 127 + xy: 775, 1089 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -ore-coal-stone-icon-small +ore-thorium-icon-small rotate: false - xy: 1424, 143 + xy: 1814, 802 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -ore-coal-stone1 +ore-titanium-icon-full rotate: false - xy: 995, 341 + xy: 1505, 951 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-coal-stone2 +ore-titanium-icon-medium rotate: false - xy: 995, 307 + xy: 1505, 951 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ore-coal-stone3 +ore-titanium-icon-large rotate: false - xy: 995, 273 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-stone-icon-full - rotate: false - xy: 995, 273 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-stone-icon-medium - rotate: false - xy: 995, 273 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-holostone-icon-large - rotate: false - xy: 1437, 1084 + xy: 825, 1139 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -ore-copper-holostone-icon-small +ore-titanium-icon-small rotate: false - xy: 1450, 143 + xy: 1244, 637 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -ore-copper-holostone1 - rotate: false - xy: 995, 239 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-holostone2 - rotate: false - xy: 1029, 342 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-holostone3 - rotate: false - xy: 1029, 308 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-holostone-icon-full - rotate: false - xy: 1029, 308 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-holostone-icon-medium - rotate: false - xy: 1029, 308 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-sand-icon-large - rotate: false - xy: 1437, 1034 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-copper-sand-icon-small - rotate: false - xy: 1476, 143 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-copper-sand1 - rotate: false - xy: 1029, 274 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-sand2 - rotate: false - xy: 1029, 240 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-sand3 - rotate: false - xy: 1003, 205 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-sand-icon-full - rotate: false - xy: 1003, 205 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-sand-icon-medium - rotate: false - xy: 1003, 205 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-stained-stone-icon-large - rotate: false - xy: 1437, 984 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-copper-stained-stone-icon-small - rotate: false - xy: 1397, 117 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-copper-stained-stone-red-icon-large - rotate: false - xy: 1487, 1089 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-copper-stained-stone-red-icon-small - rotate: false - xy: 1423, 117 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-copper-stained-stone-red1 - rotate: false - xy: 1037, 206 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-stained-stone-red2 - rotate: false - xy: 1037, 172 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-stained-stone-red3 - rotate: false - xy: 1037, 138 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-stained-stone-red-icon-full - rotate: false - xy: 1037, 138 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-stained-stone-red-icon-medium - rotate: false - xy: 1037, 138 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-stained-stone1 - rotate: false - xy: 1003, 171 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-stained-stone2 - rotate: false - xy: 1003, 137 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-stained-stone3 - rotate: false - xy: 1003, 103 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-stained-stone-icon-full - rotate: false - xy: 1003, 103 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-stained-stone-icon-medium - rotate: false - xy: 1003, 103 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-stone-icon-large - rotate: false - xy: 1487, 1039 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-copper-stone-icon-small - rotate: false - xy: 1449, 117 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-copper-stone1 - rotate: false - xy: 1037, 104 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-stone2 - rotate: false - xy: 1045, 477 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-stone3 - rotate: false - xy: 1079, 477 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-stone-icon-full - rotate: false - xy: 1079, 477 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-stone-icon-medium - rotate: false - xy: 1079, 477 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-holostone-icon-large - rotate: false - xy: 1487, 989 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-lead-holostone-icon-small - rotate: false - xy: 1475, 117 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-lead-holostone1 - rotate: false - xy: 1113, 477 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-holostone2 - rotate: false - xy: 1147, 476 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-holostone3 - rotate: false - xy: 1181, 476 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-holostone-icon-full - rotate: false - xy: 1181, 476 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-holostone-icon-medium - rotate: false - xy: 1181, 476 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-sand-icon-large - rotate: false - xy: 1537, 1047 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-lead-sand-icon-small - rotate: false - xy: 1502, 135 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-lead-sand1 - rotate: false - xy: 1215, 476 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-sand2 - rotate: false - xy: 1249, 476 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-sand3 - rotate: false - xy: 1283, 467 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-sand-icon-full - rotate: false - xy: 1283, 467 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-sand-icon-medium - rotate: false - xy: 1283, 467 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-stained-stone-icon-large - rotate: false - xy: 1537, 997 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-lead-stained-stone-icon-small - rotate: false - xy: 1528, 135 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-lead-stained-stone-red-icon-large - rotate: false - xy: 1587, 1047 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-lead-stained-stone-red-icon-small - rotate: false - xy: 1554, 135 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-lead-stained-stone-red1 - rotate: false - xy: 1419, 451 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-stained-stone-red2 - rotate: false - xy: 1453, 451 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-stained-stone-red3 - rotate: false - xy: 1487, 451 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-stained-stone-red-icon-full - rotate: false - xy: 1487, 451 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-stained-stone-red-icon-medium - rotate: false - xy: 1487, 451 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-stained-stone1 - rotate: false - xy: 1317, 467 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-stained-stone2 - rotate: false - xy: 1351, 454 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-stained-stone3 - rotate: false - xy: 1385, 454 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-stained-stone-icon-full - rotate: false - xy: 1385, 454 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-stained-stone-icon-medium - rotate: false - xy: 1385, 454 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-stone-icon-large - rotate: false - xy: 1587, 997 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-lead-stone-icon-small - rotate: false - xy: 1580, 135 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-lead-stone1 - rotate: false - xy: 1521, 443 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-stone2 - rotate: false - xy: 1555, 443 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-stone3 - rotate: false - xy: 1589, 443 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-stone-icon-full - rotate: false - xy: 1589, 443 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-stone-icon-medium - rotate: false - xy: 1589, 443 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-holostone-icon-large - rotate: false - xy: 1637, 1047 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-scrap-holostone-icon-small - rotate: false - xy: 1606, 135 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-scrap-holostone1 - rotate: false - xy: 1623, 443 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-holostone2 - rotate: false - xy: 1037, 70 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-holostone3 - rotate: false - xy: 1013, 36 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-holostone-icon-full - rotate: false - xy: 1013, 36 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-holostone-icon-medium - rotate: false - xy: 1013, 36 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-sand-icon-large - rotate: false - xy: 1637, 997 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-scrap-sand-icon-small - rotate: false - xy: 1632, 135 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-scrap-sand1 - rotate: false - xy: 1013, 2 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-sand2 - rotate: false - xy: 1047, 36 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-sand3 - rotate: false - xy: 1047, 2 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-sand-icon-full - rotate: false - xy: 1047, 2 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-sand-icon-medium - rotate: false - xy: 1047, 2 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-snow-icon-large - rotate: false - xy: 1687, 1047 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-scrap-snow-icon-small - rotate: false - xy: 1658, 135 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-scrap-snow1 - rotate: false - xy: 1045, 443 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-snow2 - rotate: false - xy: 1045, 409 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-snow3 - rotate: false - xy: 1079, 443 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-snow-icon-full - rotate: false - xy: 1079, 443 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-snow-icon-medium - rotate: false - xy: 1079, 443 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-stained-stone-icon-large - rotate: false - xy: 1687, 997 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-scrap-stained-stone-icon-small - rotate: false - xy: 1684, 135 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-scrap-stained-stone-red-icon-large - rotate: false - xy: 1737, 1047 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-scrap-stained-stone-red-icon-small - rotate: false - xy: 1710, 135 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-scrap-stained-stone-red1 - rotate: false - xy: 1147, 442 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-stained-stone-red2 - rotate: false - xy: 1181, 442 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-stained-stone-red3 - rotate: false - xy: 1215, 442 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-stained-stone-red-icon-full - rotate: false - xy: 1215, 442 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-stained-stone-red-icon-medium - rotate: false - xy: 1215, 442 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-stained-stone1 - rotate: false - xy: 1113, 443 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-stained-stone2 - rotate: false - xy: 1079, 409 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-stained-stone3 - rotate: false - xy: 1113, 409 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-stained-stone-icon-full - rotate: false - xy: 1113, 409 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-stained-stone-icon-medium - rotate: false - xy: 1113, 409 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-stone-icon-large - rotate: false - xy: 1737, 997 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-scrap-stone-icon-small - rotate: false - xy: 1736, 135 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-scrap-stone1 - rotate: false - xy: 1249, 442 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-stone2 - rotate: false - xy: 1147, 408 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-stone3 - rotate: false - xy: 1181, 408 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-stone-icon-full - rotate: false - xy: 1181, 408 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-stone-icon-medium - rotate: false - xy: 1181, 408 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-holostone-icon-large - rotate: false - xy: 1787, 1047 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-thorium-holostone-icon-small - rotate: false - xy: 1762, 135 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-thorium-holostone1 - rotate: false - xy: 1215, 408 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-holostone2 - rotate: false - xy: 1249, 408 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-holostone3 - rotate: false - xy: 1283, 433 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-holostone-icon-full - rotate: false - xy: 1283, 433 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-holostone-icon-medium - rotate: false - xy: 1283, 433 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-sand-icon-large - rotate: false - xy: 1787, 997 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-thorium-sand-icon-small - rotate: false - xy: 1788, 135 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-thorium-sand1 - rotate: false - xy: 1317, 433 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-sand2 - rotate: false - xy: 1283, 399 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-sand3 - rotate: false - xy: 1317, 399 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-sand-icon-full - rotate: false - xy: 1317, 399 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-sand-icon-medium - rotate: false - xy: 1317, 399 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-stained-stone-icon-large - rotate: false - xy: 1837, 1047 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-thorium-stained-stone-icon-small - rotate: false - xy: 1814, 135 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-thorium-stained-stone-red-icon-large - rotate: false - xy: 1837, 997 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-thorium-stained-stone-red-icon-small - rotate: false - xy: 1840, 135 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-thorium-stained-stone-red1 - rotate: false - xy: 1453, 417 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-stained-stone-red2 - rotate: false - xy: 1487, 417 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-stained-stone-red3 - rotate: false - xy: 1521, 409 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-stained-stone-red-icon-full - rotate: false - xy: 1521, 409 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-stained-stone-red-icon-medium - rotate: false - xy: 1521, 409 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-stained-stone1 - rotate: false - xy: 1351, 420 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-stained-stone2 - rotate: false - xy: 1385, 420 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-stained-stone3 - rotate: false - xy: 1419, 417 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-stained-stone-icon-full - rotate: false - xy: 1419, 417 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-stained-stone-icon-medium - rotate: false - xy: 1419, 417 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-stone-icon-large - rotate: false - xy: 1887, 1047 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-thorium-stone-icon-small - rotate: false - xy: 1866, 135 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-thorium-stone1 - rotate: false - xy: 1555, 409 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-stone2 - rotate: false - xy: 1589, 409 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-stone3 - rotate: false - xy: 1623, 409 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-stone-icon-full - rotate: false - xy: 1623, 409 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-stone-icon-medium - rotate: false - xy: 1623, 409 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-holostone-icon-large - rotate: false - xy: 1887, 997 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-titanium-holostone-icon-small - rotate: false - xy: 1892, 135 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-titanium-holostone1 - rotate: false - xy: 1351, 386 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-holostone2 - rotate: false - xy: 1385, 386 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-holostone3 - rotate: false - xy: 1419, 383 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-holostone-icon-full - rotate: false - xy: 1419, 383 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-holostone-icon-medium - rotate: false - xy: 1419, 383 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-sand-icon-large - rotate: false - xy: 953, 177 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-titanium-sand-icon-small - rotate: false - xy: 1918, 135 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-titanium-sand1 - rotate: false - xy: 1453, 383 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-sand2 - rotate: false - xy: 1487, 383 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-sand3 - rotate: false - xy: 1521, 375 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-sand-icon-full - rotate: false - xy: 1521, 375 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-sand-icon-medium - rotate: false - xy: 1521, 375 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-stained-stone-icon-large - rotate: false - xy: 953, 127 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-titanium-stained-stone-icon-small - rotate: false - xy: 1944, 135 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-titanium-stained-stone-red-icon-large - rotate: false - xy: 703, 115 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-titanium-stained-stone-red-icon-small - rotate: false - xy: 1970, 135 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-titanium-stained-stone-red1 - rotate: false - xy: 1657, 417 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-stained-stone-red2 - rotate: false - xy: 1657, 383 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-stained-stone-red3 - rotate: false - xy: 1691, 417 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-stained-stone-red-icon-full - rotate: false - xy: 1691, 417 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-stained-stone-red-icon-medium - rotate: false - xy: 1691, 417 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-stained-stone1 - rotate: false - xy: 1555, 375 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-stained-stone2 - rotate: false - xy: 1589, 375 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-stained-stone3 - rotate: false - xy: 1623, 375 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-stained-stone-icon-full - rotate: false - xy: 1623, 375 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-stained-stone-icon-medium - rotate: false - xy: 1623, 375 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-stone-icon-large - rotate: false - xy: 753, 115 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-titanium-stone-icon-small - rotate: false - xy: 1996, 135 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-titanium-stone1 - rotate: false - xy: 1691, 383 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-stone2 - rotate: false - xy: 1725, 417 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-stone3 - rotate: false - xy: 1725, 383 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-stone-icon-full - rotate: false - xy: 1725, 383 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-stone-icon-medium - rotate: false - xy: 1725, 383 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 overdrive-projector-icon-large rotate: false - xy: 803, 77 + xy: 725, 989 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 overdrive-projector-icon-medium rotate: false - xy: 1759, 417 + xy: 1539, 930 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 overdrive-projector-icon-small rotate: false - xy: 1501, 109 + xy: 1270, 636 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 overflow-gate-icon-large rotate: false - xy: 853, 77 + xy: 775, 1039 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 overflow-gate-icon-small rotate: false - xy: 1527, 109 + xy: 1296, 636 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 phantom-factory-icon-full rotate: false - xy: 771, 741 + xy: 1975, 1383 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 phantom-factory-icon-large rotate: false - xy: 903, 77 + xy: 825, 1089 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 phantom-factory-icon-medium rotate: false - xy: 1793, 417 + xy: 1607, 930 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phantom-factory-icon-small rotate: false - xy: 1553, 109 + xy: 1322, 636 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 phase-conduit-icon-large rotate: false - xy: 953, 77 + xy: 725, 939 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 phase-conduit-icon-small rotate: false - xy: 1579, 109 + xy: 1502, 776 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 phase-conveyor-icon-large rotate: false - xy: 1537, 947 + xy: 775, 989 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 phase-conveyor-icon-small rotate: false - xy: 1605, 109 + xy: 1528, 776 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 phase-wall-icon-large rotate: false - xy: 1587, 947 + xy: 825, 1039 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 phase-wall-icon-small rotate: false - xy: 1631, 109 + xy: 1554, 776 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 phase-wall-large-icon-large rotate: false - xy: 1637, 947 + xy: 725, 889 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 phase-wall-large-icon-medium rotate: false - xy: 1963, 417 + xy: 1947, 913 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-wall-large-icon-small rotate: false - xy: 1657, 109 + xy: 1580, 776 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 phase-weaver-icon-full rotate: false - xy: 747, 543 + xy: 1381, 1297 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 phase-weaver-icon-large rotate: false - xy: 1687, 947 + xy: 775, 939 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 phase-weaver-icon-medium rotate: false - xy: 1963, 383 + xy: 1981, 913 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-weaver-icon-small rotate: false - xy: 1683, 109 + xy: 1606, 776 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -pine-icon-large +pine-icon-medium rotate: false - xy: 1737, 947 - size: 48, 48 - orig: 48, 48 + xy: 2015, 913 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 pine-icon-small rotate: false - xy: 1709, 109 + xy: 1632, 776 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 plastanium-compressor-icon-large rotate: false - xy: 1787, 947 + xy: 825, 989 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 plastanium-compressor-icon-medium rotate: false - xy: 1997, 383 + xy: 1151, 855 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 plastanium-compressor-icon-small rotate: false - xy: 1735, 109 + xy: 1658, 776 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 pneumatic-drill-icon-full rotate: false - xy: 813, 609 + xy: 1711, 1297 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 pneumatic-drill-icon-large rotate: false - xy: 1837, 947 + xy: 725, 839 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 pneumatic-drill-icon-medium rotate: false - xy: 1657, 349 + xy: 1151, 821 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pneumatic-drill-icon-small rotate: false - xy: 1761, 109 + xy: 1684, 776 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 power-node-icon-large rotate: false - xy: 1887, 947 + xy: 775, 889 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 power-node-icon-small rotate: false - xy: 1787, 109 + xy: 1710, 776 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 power-node-large-icon-large rotate: false - xy: 1487, 939 + xy: 825, 939 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 power-node-large-icon-medium rotate: false - xy: 1725, 349 + xy: 1217, 913 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 power-node-large-icon-small rotate: false - xy: 1813, 109 + xy: 1736, 776 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 power-source-icon-large rotate: false - xy: 1477, 889 + xy: 775, 839 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 power-source-icon-small rotate: false - xy: 1839, 109 + xy: 1762, 776 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 power-void-icon-large rotate: false - xy: 1477, 839 + xy: 825, 889 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 power-void-icon-small rotate: false - xy: 1865, 109 + xy: 1788, 776 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 pulse-conduit-icon-full rotate: false - xy: 1895, 349 + xy: 1251, 895 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-icon-large rotate: false - xy: 1527, 889 + xy: 825, 839 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 pulse-conduit-icon-small rotate: false - xy: 1891, 109 + xy: 1814, 776 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 pulverizer-icon-full rotate: false - xy: 1063, 273 + xy: 1421, 875 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulverizer-icon-large rotate: false - xy: 1527, 839 + xy: 725, 789 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 pulverizer-icon-small rotate: false - xy: 1917, 109 + xy: 554, 554 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 pyratite-mixer-icon-large rotate: false - xy: 1577, 897 + xy: 775, 789 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 pyratite-mixer-icon-medium rotate: false - xy: 1097, 273 + xy: 1489, 883 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pyratite-mixer-icon-small rotate: false - xy: 1943, 109 + xy: 580, 554 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 repair-point rotate: false - xy: 1131, 374 + xy: 1523, 896 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 repair-point-icon-full rotate: false - xy: 1131, 340 + xy: 1591, 896 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 repair-point-icon-large rotate: false - xy: 1627, 897 + xy: 724, 739 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 repair-point-icon-small rotate: false - xy: 1969, 109 + xy: 551, 528 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 revenant-factory-icon-full rotate: false - xy: 1176, 1691 + xy: 1306, 1789 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 revenant-factory-icon-large rotate: false - xy: 1627, 847 + xy: 774, 739 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 revenant-factory-icon-medium rotate: false - xy: 1199, 374 + xy: 1625, 896 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 revenant-factory-icon-small rotate: false - xy: 1995, 109 + xy: 577, 528 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 ripple rotate: false - xy: 845, 1397 + xy: 1885, 1495 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 ripple-icon-full rotate: false - xy: 943, 1397 + xy: 163, 1201 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 ripple-icon-large rotate: false - xy: 1677, 847 + xy: 875, 1181 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 ripple-icon-medium rotate: false - xy: 1131, 306 + xy: 1659, 896 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ripple-icon-small rotate: false - xy: 1345, 94 + xy: 555, 502 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 rocks-icon-large rotate: false - xy: 1777, 897 + xy: 925, 1181 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 rocks-icon-small rotate: false - xy: 1371, 94 + xy: 555, 476 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 rotary-pump-icon-large rotate: false - xy: 1777, 847 + xy: 875, 1131 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 rotary-pump-icon-medium rotate: false - xy: 1165, 306 + xy: 1693, 896 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 rotary-pump-icon-small rotate: false - xy: 1397, 91 + xy: 555, 450 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 router-icon-large rotate: false - xy: 1827, 897 + xy: 975, 1181 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 router-icon-small rotate: false - xy: 1423, 91 + xy: 555, 424 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 rtg-generator-icon-large rotate: false - xy: 1827, 847 + xy: 875, 1081 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 rtg-generator-icon-medium rotate: false - xy: 1199, 306 + xy: 1761, 896 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 rtg-generator-icon-small rotate: false - xy: 1449, 91 + xy: 555, 398 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +salt-icon-large + rotate: false + xy: 925, 1131 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +salt-icon-small + rotate: false + xy: 555, 372 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 salvo rotate: false - xy: 1303, 1284 + xy: 253, 739 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 salvo-icon-full rotate: false - xy: 1279, 1152 + xy: 985, 1331 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 salvo-icon-large rotate: false - xy: 1877, 897 + xy: 1025, 1181 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 salvo-icon-medium rotate: false - xy: 1233, 306 + xy: 1829, 896 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 salvo-icon-small rotate: false - xy: 1475, 91 + xy: 555, 346 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -sand-edge - rotate: false - xy: 1, 211 - size: 288, 96 - orig: 288, 96 - offset: 0, 0 - index: -1 sand-icon-large rotate: false - xy: 1877, 847 + xy: 875, 1031 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 sand-icon-small rotate: false - xy: 1501, 83 + xy: 555, 320 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -sand-water-edge - rotate: false - xy: 1, 113 - size: 288, 96 - orig: 288, 96 - offset: 0, 0 - index: -1 sand-water-icon-large rotate: false - xy: 1927, 897 + xy: 925, 1081 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 sand-water-icon-small rotate: false - xy: 1527, 83 + xy: 555, 294 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +sandrocks-icon-large + rotate: false + xy: 975, 1131 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +sandrocks-icon-small + rotate: false + xy: 555, 268 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +scatter + rotate: false + xy: 1183, 1231 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +scatter-icon-full + rotate: false + xy: 1249, 1231 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +scatter-icon-large + rotate: false + xy: 875, 981 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +scatter-icon-medium + rotate: false + xy: 1523, 862 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scatter-icon-small + rotate: false + xy: 555, 242 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 scrap-wall-gigantic-icon-large rotate: false - xy: 1927, 847 + xy: 925, 1031 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 scrap-wall-gigantic-icon-medium rotate: false - xy: 1301, 263 + xy: 1693, 862 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scrap-wall-gigantic-icon-small rotate: false - xy: 1553, 83 + xy: 555, 216 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 scrap-wall-huge-icon-large rotate: false - xy: 1577, 797 + xy: 975, 1081 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 scrap-wall-huge-icon-medium rotate: false - xy: 1335, 352 + xy: 1727, 862 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scrap-wall-huge-icon-small rotate: false - xy: 1579, 83 + xy: 555, 190 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 scrap-wall-icon-large rotate: false - xy: 1627, 797 + xy: 1025, 1131 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 scrap-wall-icon-small rotate: false - xy: 1605, 83 + xy: 555, 164 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 scrap-wall-large-icon-large rotate: false - xy: 1677, 797 + xy: 875, 931 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 scrap-wall-large-icon-medium rotate: false - xy: 1369, 352 + xy: 1761, 862 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scrap-wall-large-icon-small rotate: false - xy: 1631, 83 + xy: 555, 138 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 separator-icon-large rotate: false - xy: 1727, 797 + xy: 925, 981 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 separator-icon-medium rotate: false - xy: 1335, 284 + xy: 1829, 862 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 separator-icon-small rotate: false - xy: 1709, 83 + xy: 555, 33 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +shale-boulder-icon-large + rotate: false + xy: 975, 1031 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +shale-boulder-icon-small + rotate: false + xy: 581, 502 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +shale-icon-large + rotate: false + xy: 1025, 1081 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +shale-icon-small + rotate: false + xy: 581, 476 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +shalerocks-icon-large + rotate: false + xy: 875, 881 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +shalerocks-icon-small + rotate: false + xy: 581, 450 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 shock-mine-icon-large rotate: false - xy: 1777, 797 + xy: 925, 931 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 shock-mine-icon-small rotate: false - xy: 1735, 83 + xy: 581, 424 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 silicon-smelter-icon-large rotate: false - xy: 1877, 797 + xy: 1025, 1031 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 silicon-smelter-icon-medium rotate: false - xy: 1335, 250 + xy: 1897, 887 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 silicon-smelter-icon-small rotate: false - xy: 1761, 83 + xy: 581, 398 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -snow-edge - rotate: false - xy: 1, 15 - size: 288, 96 - orig: 288, 96 - offset: 0, 0 - index: -1 snow-icon-large rotate: false - xy: 1927, 797 + xy: 875, 831 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 snow-icon-small rotate: false - xy: 1787, 83 + xy: 581, 372 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 snowrocks-icon-large rotate: false - xy: 1937, 1047 + xy: 925, 881 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 snowrocks-icon-small rotate: false - xy: 1813, 83 + xy: 581, 346 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 solar-panel-icon-large rotate: false - xy: 1937, 997 + xy: 975, 931 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 solar-panel-icon-small rotate: false - xy: 1839, 83 + xy: 581, 320 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 solar-panel-large-icon-large rotate: false - xy: 1937, 947 + xy: 1025, 981 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 solar-panel-large-icon-medium rotate: false - xy: 1437, 281 + xy: 1931, 879 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 solar-panel-large-icon-small rotate: false - xy: 1865, 83 + xy: 581, 294 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 sorter-icon-large rotate: false - xy: 1977, 897 + xy: 925, 831 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 sorter-icon-small rotate: false - xy: 1891, 83 + xy: 581, 268 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 spawn-icon-large rotate: false - xy: 1977, 847 + xy: 975, 881 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 spawn-icon-small rotate: false - xy: 1917, 83 + xy: 581, 242 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 spectre rotate: false - xy: 1826, 1691 + xy: 453, 1628 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 spectre-icon-full rotate: false - xy: 477, 1561 + xy: 583, 1659 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 spectre-icon-large rotate: false - xy: 1977, 797 + xy: 1025, 931 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 spectre-icon-medium rotate: false - xy: 1437, 247 + xy: 1965, 845 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 spectre-icon-small rotate: false - xy: 1943, 83 + xy: 581, 216 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 spirit-factory-icon-full rotate: false - xy: 1731, 1363 + xy: 1777, 1231 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spirit-factory-icon-large rotate: false - xy: 1201, 838 + xy: 1025, 881 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 spirit-factory-icon-medium rotate: false - xy: 1471, 247 + xy: 1999, 845 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 spirit-factory-icon-small rotate: false - xy: 1969, 83 + xy: 581, 190 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 spore-cluster-icon-large rotate: false - xy: 1151, 788 + xy: 1025, 831 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 spore-cluster-icon-medium rotate: false - xy: 1505, 341 + xy: 1523, 828 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 spore-cluster-icon-small rotate: false - xy: 1995, 83 + xy: 581, 164 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +spore-moss-icon-large + rotate: false + xy: 875, 781 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +spore-moss-icon-small + rotate: false + xy: 581, 138 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +spore-pine-icon-medium + rotate: false + xy: 1557, 828 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spore-pine-icon-small + rotate: false + xy: 581, 112 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 spore-press-icon-full rotate: false - xy: 1633, 1297 + xy: 517, 1366 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spore-press-icon-large rotate: false - xy: 1251, 838 + xy: 925, 781 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 spore-press-icon-medium rotate: false - xy: 1539, 341 + xy: 1591, 828 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 spore-press-icon-small rotate: false - xy: 1709, 57 + xy: 581, 86 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -stained-boulder-icon-large - rotate: false - xy: 1201, 788 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -stained-boulder-icon-small - rotate: false - xy: 1735, 57 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -stained-rocks-icon-large - rotate: false - xy: 1251, 788 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -stained-rocks-icon-small - rotate: false - xy: 1761, 57 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -stained-rocks-red-icon-large - rotate: false - xy: 1151, 738 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -stained-rocks-red-icon-small - rotate: false - xy: 1787, 57 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -stained-rocks-yellow-icon-large - rotate: false - xy: 1201, 738 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -stained-rocks-yellow-icon-small - rotate: false - xy: 1813, 57 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -stained-stone-edge - rotate: false - xy: 582, 1951 - size: 288, 96 - orig: 288, 96 - offset: 0, 0 - index: -1 -stained-stone-icon-large - rotate: false - xy: 1251, 738 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -stained-stone-icon-small - rotate: false - xy: 1839, 57 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -stained-stone-red-edge - rotate: false - xy: 872, 1951 - size: 288, 96 - orig: 288, 96 - offset: 0, 0 - index: -1 -stained-stone-red-icon-large - rotate: false - xy: 1301, 834 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -stained-stone-red-icon-small - rotate: false - xy: 1865, 57 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -stained-stone-yellow-edge - rotate: false - xy: 1162, 1951 - size: 288, 96 - orig: 288, 96 - offset: 0, 0 - index: -1 -stained-stone-yellow-icon-large - rotate: false - xy: 1301, 784 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -stained-stone-yellow-icon-small - rotate: false - xy: 1891, 57 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -stone-edge - rotate: false - xy: 1452, 1951 - size: 288, 96 - orig: 288, 96 - offset: 0, 0 - index: -1 stone-icon-large rotate: false - xy: 1301, 734 + xy: 975, 781 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 stone-icon-small rotate: false - xy: 1917, 57 + xy: 581, 60 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 surge-tower-icon-large rotate: false - xy: 1351, 826 + xy: 1025, 781 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 surge-tower-icon-medium rotate: false - xy: 1675, 247 + xy: 1625, 828 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 surge-tower-icon-small rotate: false - xy: 1943, 57 + xy: 581, 34 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 surge-wall-icon-large rotate: false - xy: 1401, 826 + xy: 874, 731 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 surge-wall-icon-small rotate: false - xy: 1969, 57 + xy: 555, 7 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 surge-wall-large-icon-large rotate: false - xy: 1351, 776 + xy: 924, 731 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 surge-wall-large-icon-medium rotate: false - xy: 1743, 315 + xy: 1693, 828 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 surge-wall-large-icon-small rotate: false - xy: 1995, 57 + xy: 581, 8 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 swarmer rotate: false - xy: 845, 905 + xy: 393, 1300 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 swarmer-icon-full rotate: false - xy: 911, 905 + xy: 459, 1300 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 swarmer-icon-large rotate: false - xy: 1351, 726 + xy: 1024, 731 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 swarmer-icon-medium rotate: false - xy: 1709, 247 + xy: 1727, 828 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 swarmer-icon-small rotate: false - xy: 1683, 46 + xy: 603, 528 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -tar-edge - rotate: false - xy: 1742, 1951 - size: 288, 96 - orig: 288, 96 - offset: 0, 0 - index: -1 tar-icon-large rotate: false - xy: 1401, 726 + xy: 1075, 1181 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 tar-icon-small rotate: false - xy: 1709, 31 + xy: 606, 554 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 tau-mech-pad-icon-large rotate: false - xy: 1451, 739 + xy: 1175, 1181 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 tau-mech-pad-icon-medium rotate: false - xy: 1777, 315 + xy: 1761, 828 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 tau-mech-pad-icon-small rotate: false - xy: 1735, 31 + xy: 607, 502 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 thermal-generator-icon-large rotate: false - xy: 1501, 739 + xy: 1075, 1081 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 thermal-generator-icon-medium rotate: false - xy: 1743, 247 + xy: 1795, 828 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 thermal-generator-icon-small rotate: false - xy: 1761, 31 + xy: 607, 476 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 thermal-pump-icon-large rotate: false - xy: 1551, 747 + xy: 1125, 1131 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 thermal-pump-icon-medium rotate: false - xy: 1777, 281 + xy: 1829, 828 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 thermal-pump-icon-small rotate: false - xy: 1787, 31 + xy: 607, 450 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 thorium-reactor-icon-large rotate: false - xy: 1601, 747 + xy: 1225, 1181 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 thorium-reactor-icon-medium rotate: false - xy: 1845, 315 + xy: 1863, 819 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 thorium-reactor-icon-small rotate: false - xy: 1813, 31 + xy: 607, 424 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 thorium-wall-icon-large rotate: false - xy: 1651, 747 + xy: 1075, 1031 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 thorium-wall-icon-small rotate: false - xy: 1839, 31 + xy: 607, 398 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 thorium-wall-large-icon-large rotate: false - xy: 1701, 747 + xy: 1125, 1081 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 thorium-wall-large-icon-medium rotate: false - xy: 1845, 281 + xy: 1931, 811 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 thorium-wall-large-icon-small rotate: false - xy: 1865, 31 + xy: 607, 372 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 thruster-icon-large rotate: false - xy: 1751, 747 + xy: 1175, 1131 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 thruster-icon-medium rotate: false - xy: 1879, 315 + xy: 1965, 811 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 thruster-icon-small rotate: false - xy: 1891, 31 + xy: 607, 346 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 titan-factory-icon-full rotate: false - xy: 1237, 1397 + xy: 131, 123 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 titan-factory-icon-large rotate: false - xy: 1801, 747 + xy: 1275, 1181 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 titan-factory-icon-medium rotate: false - xy: 1845, 247 + xy: 1999, 811 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titan-factory-icon-small rotate: false - xy: 1917, 31 + xy: 607, 320 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 titanium-conveyor-icon-large rotate: false - xy: 1851, 747 + xy: 1075, 981 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 titanium-conveyor-icon-small rotate: false - xy: 1943, 31 + xy: 607, 294 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 titanium-wall-icon-large rotate: false - xy: 1901, 747 + xy: 1125, 1031 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 titanium-wall-icon-small rotate: false - xy: 1969, 31 + xy: 607, 268 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 titanium-wall-large-icon-large rotate: false - xy: 1951, 747 + xy: 1175, 1081 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 titanium-wall-large-icon-medium rotate: false - xy: 1981, 213 + xy: 495, 318 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-wall-large-icon-small rotate: false - xy: 1995, 31 + xy: 607, 242 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 trident-ship-pad-icon-large rotate: false - xy: 1451, 689 + xy: 1225, 1131 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 trident-ship-pad-icon-medium rotate: false - xy: 1071, 239 + xy: 495, 250 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 trident-ship-pad-icon-small rotate: false - xy: 1170, 178 + xy: 607, 216 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 turbine-generator-icon-large rotate: false - xy: 1501, 689 + xy: 1325, 1181 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 turbine-generator-icon-medium rotate: false - xy: 1071, 205 + xy: 495, 216 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 turbine-generator-icon-small rotate: false - xy: 1196, 178 + xy: 607, 190 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 unit-icon-chaos-array rotate: false - xy: 737, 1561 + xy: 843, 1659 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 unit-icon-crawler rotate: false - xy: 1551, 697 + xy: 1075, 931 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 unit-icon-dagger rotate: false - xy: 1601, 697 + xy: 1125, 981 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 unit-icon-eradicator rotate: false - xy: 291, 241 + xy: 1, 731 size: 152, 124 orig: 152, 124 offset: 0, 0 index: -1 unit-icon-eruptor rotate: false - xy: 969, 773 + xy: 319, 970 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 unit-icon-fortress rotate: false - xy: 903, 707 + xy: 385, 1036 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 unit-icon-titan rotate: false - xy: 1035, 773 + xy: 451, 1102 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 unloader-icon-large rotate: false - xy: 1651, 697 + xy: 1175, 1031 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 unloader-icon-small rotate: false - xy: 1188, 152 + xy: 607, 164 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 vault-icon-large rotate: false - xy: 1701, 697 + xy: 1225, 1081 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 vault-icon-medium rotate: false - xy: 1071, 137 + xy: 495, 148 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 vault-icon-small rotate: false - xy: 1137, 2 + xy: 607, 138 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -water-edge - rotate: false - xy: 291, 897 - size: 288, 96 - orig: 288, 96 - offset: 0, 0 - index: -1 water-extractor-icon-full rotate: false - xy: 1035, 707 + xy: 385, 970 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 water-extractor-icon-large rotate: false - xy: 1751, 697 + xy: 1275, 1131 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 water-extractor-icon-medium rotate: false - xy: 1105, 238 + xy: 495, 114 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 water-extractor-icon-small rotate: false - xy: 1163, 4 + xy: 607, 112 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 water-icon-large rotate: false - xy: 1801, 697 + xy: 1375, 1181 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 water-icon-small rotate: false - xy: 1189, 4 + xy: 607, 86 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 wave rotate: false - xy: 945, 575 + xy: 451, 970 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 wave-icon-full rotate: false - xy: 1011, 641 + xy: 319, 772 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 wave-icon-large rotate: false - xy: 1851, 697 + xy: 1075, 881 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 wave-icon-medium rotate: false - xy: 1139, 238 + xy: 495, 80 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 wave-icon-small rotate: false - xy: 2022, 135 + xy: 607, 60 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 white-tree-dead-icon-large rotate: false - xy: 1901, 697 + xy: 1125, 931 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 white-tree-dead-icon-medium rotate: false - xy: 1105, 204 + xy: 485, 730 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 white-tree-dead-icon-small rotate: false - xy: 2021, 109 + xy: 607, 34 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 white-tree-icon-large rotate: false - xy: 1951, 697 + xy: 1175, 981 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 white-tree-icon-medium rotate: false - xy: 1173, 238 + xy: 519, 730 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 white-tree-icon-small rotate: false - xy: 2021, 83 + xy: 607, 8 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 wraith-factory-icon-full rotate: false - xy: 913, 509 + xy: 451, 904 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 wraith-factory-icon-large rotate: false - xy: 1601, 647 + xy: 1275, 1081 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 wraith-factory-icon-medium rotate: false - xy: 1105, 170 + xy: 499, 696 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 wraith-factory-icon-small rotate: false - xy: 2021, 57 + xy: 629, 528 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-biomatter rotate: false - xy: 1841, 519 + xy: 1573, 1032 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-blast-compound rotate: false - xy: 1875, 553 + xy: 1539, 998 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-coal rotate: false - xy: 1841, 485 + xy: 1607, 1032 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-copper rotate: false - xy: 1875, 519 + xy: 1573, 998 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-graphite rotate: false - xy: 1909, 553 + xy: 1641, 1032 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-lead rotate: false - xy: 1875, 485 + xy: 1607, 998 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-metaglass rotate: false - xy: 1909, 519 + xy: 1675, 1032 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-phase-fabric rotate: false - xy: 1943, 553 + xy: 1641, 998 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-plastanium rotate: false - xy: 1909, 485 + xy: 1709, 1032 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-pyratite rotate: false - xy: 1943, 519 + xy: 1675, 998 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-sand rotate: false - xy: 1943, 485 + xy: 1743, 1032 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-scrap rotate: false - xy: 1977, 553 + xy: 1709, 998 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-silicon rotate: false - xy: 1977, 519 + xy: 1777, 1032 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-spore-pod rotate: false - xy: 1989, 587 + xy: 1811, 1032 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-surge-alloy rotate: false - xy: 2011, 553 + xy: 1777, 998 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-thorium rotate: false - xy: 2011, 519 + xy: 1845, 1032 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-titanium rotate: false - xy: 2011, 485 + xy: 1811, 998 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-cryofluid rotate: false - xy: 1945, 1163 + xy: 1947, 981 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-oil rotate: false - xy: 1979, 1165 + xy: 2015, 981 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-slag rotate: false - xy: 1979, 1097 + xy: 1675, 964 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-water rotate: false - xy: 1987, 995 + xy: 1777, 964 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 alpha-mech rotate: false - xy: 511, 291 + xy: 349, 664 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 alpha-mech-base rotate: false - xy: 577, 365 + xy: 295, 556 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 alpha-mech-leg rotate: false - xy: 627, 365 + xy: 349, 614 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 delta-mech rotate: false - xy: 1707, 1197 + xy: 395, 164 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 delta-mech-base rotate: false - xy: 1757, 1197 + xy: 395, 114 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 delta-mech-leg rotate: false - xy: 1807, 1197 + xy: 345, 64 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 omega-mech rotate: false - xy: 455, 1 + xy: 517, 996 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 omega-mech-armor rotate: false - xy: 639, 675 + xy: 1777, 1363 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 omega-mech-base rotate: false - xy: 479, 117 + xy: 517, 938 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 omega-mech-leg rotate: false - xy: 513, 59 + xy: 517, 880 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 tau-mech rotate: false - xy: 635, 415 + xy: 319, 714 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 tau-mech-base rotate: false - xy: 1451, 789 + xy: 1125, 1181 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 tau-mech-leg rotate: false - xy: 1501, 789 + xy: 1075, 1131 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 dart-ship rotate: false - xy: 1607, 1197 + xy: 395, 214 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 glaive-ship rotate: false - xy: 421, 117 + xy: 583, 1292 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 javelin-ship rotate: false - xy: 1645, 1147 + xy: 449, 522 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 javelin-ship-shield rotate: false - xy: 1745, 1147 + xy: 445, 422 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 trident-ship rotate: false - xy: 519, 391 + xy: 377, 714 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 blank rotate: false - xy: 1398, 169 + xy: 1245, 770 size: 1, 1 orig: 1, 1 offset: 0, 0 @@ -8427,21 +6271,21 @@ circle index: -1 clear rotate: false - xy: 2003, 1407 + xy: 1245, 767 size: 1, 1 orig: 1, 1 offset: 0, 0 index: -1 shape-3 rotate: false - xy: 979, 444 + xy: 451, 773 size: 63, 63 orig: 63, 63 offset: 0, 0 index: -1 bar rotate: false - xy: 1290, 123 + xy: 1219, 773 size: 27, 36 split: 9, 9, 9, 9 orig: 27, 36 @@ -8449,7 +6293,7 @@ bar index: -1 bar-top rotate: false - xy: 1139, 160 + xy: 499, 578 size: 27, 36 split: 9, 10, 9, 10 orig: 27, 36 @@ -8457,7 +6301,7 @@ bar-top index: -1 button rotate: false - xy: 1223, 709 + xy: 1741, 1202 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -8465,7 +6309,7 @@ button index: -1 button-disabled rotate: false - xy: 2011, 1642 + xy: 526, 1760 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -8473,7 +6317,7 @@ button-disabled index: -1 button-down rotate: false - xy: 2011, 1613 + xy: 1, 5 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -8481,7 +6325,7 @@ button-down index: -1 button-edge-1 rotate: false - xy: 2011, 1584 + xy: 261, 1207 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -8489,7 +6333,7 @@ button-edge-1 index: -1 button-edge-2 rotate: false - xy: 2011, 1555 + xy: 295, 69 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -8497,7 +6341,7 @@ button-edge-2 index: -1 button-edge-3 rotate: false - xy: 2011, 1526 + xy: 1551, 1202 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -8505,7 +6349,7 @@ button-edge-3 index: -1 button-edge-4 rotate: false - xy: 2011, 1497 + xy: 39, 5 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -8513,7 +6357,7 @@ button-edge-4 index: -1 button-over rotate: false - xy: 2011, 1468 + xy: 1589, 1202 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -8521,7 +6365,7 @@ button-over index: -1 button-right rotate: false - xy: 1185, 709 + xy: 1703, 1202 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -8529,7 +6373,7 @@ button-right index: -1 button-right-down rotate: false - xy: 639, 646 + xy: 1627, 1202 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -8537,7 +6381,7 @@ button-right-down index: -1 button-right-over rotate: false - xy: 837, 678 + xy: 1665, 1202 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -8545,7 +6389,7 @@ button-right-over index: -1 button-select rotate: false - xy: 1319, 135 + xy: 891, 1337 size: 24, 24 split: 4, 4, 4, 4 orig: 24, 24 @@ -8553,42 +6397,42 @@ button-select index: -1 check-off rotate: false - xy: 1207, 238 - size: 28, 32 - orig: 28, 32 + xy: 1653, 1168 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 check-on rotate: false - xy: 1237, 238 - size: 28, 32 - orig: 28, 32 + xy: 1687, 1168 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 check-on-over rotate: false - xy: 1170, 204 - size: 28, 32 - orig: 28, 32 + xy: 1721, 1168 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 check-over rotate: false - xy: 1200, 204 - size: 28, 32 - orig: 28, 32 + xy: 1755, 1168 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 clear rotate: false - xy: 1225, 1287 + xy: 333, 86 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 content-background rotate: false - xy: 1135, 667 + xy: 1855, 1202 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -8596,7 +6440,7 @@ content-background index: -1 content-background-locked rotate: false - xy: 1261, 709 + xy: 1779, 1202 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -8604,7 +6448,7 @@ content-background-locked index: -1 content-background-over rotate: false - xy: 1299, 705 + xy: 1817, 1202 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -8612,903 +6456,903 @@ content-background-over index: -1 cursor rotate: false - xy: 1045, 569 + xy: 553, 730 size: 4, 4 orig: 4, 4 offset: 0, 0 index: -1 discord-banner rotate: false - xy: 1139, 1252 + xy: 1, 34 size: 84, 45 orig: 84, 45 offset: 0, 0 index: -1 empty-sector rotate: false - xy: 1753, 621 + xy: 1369, 996 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 icon-crafting rotate: false - xy: 2031, 397 + xy: 1219, 729 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-defense rotate: false - xy: 2031, 379 + xy: 2021, 1055 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-distribution rotate: false - xy: 2031, 361 + xy: 605, 744 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-effect rotate: false - xy: 1188, 134 + xy: 1502, 831 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-liquid rotate: false - xy: 1135, 573 + xy: 633, 420 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-power rotate: false - xy: 527, 1525 + xy: 633, 258 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-production rotate: false - xy: 893, 441 + xy: 633, 240 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-turret rotate: false - xy: 625, 3 + xy: 633, 78 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-units rotate: false - xy: 437, 1000 + xy: 633, 42 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-upgrade rotate: false - xy: 473, 1000 + xy: 1840, 774 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 controller-cursor rotate: false - xy: 453, 637 + xy: 295, 51 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-about rotate: false - xy: 535, 1100 + xy: 1101, 1479 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-add rotate: false - xy: 561, 375 + xy: 973, 1659 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-admin rotate: false - xy: 623, 923 + xy: 1003, 1463 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-admin-small rotate: false - xy: 603, 257 + xy: 155, 1227 size: 6, 6 orig: 6, 6 offset: 0, 0 index: -1 icon-areaDelete rotate: false - xy: 1213, 1240 + xy: 599, 1420 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-arrow rotate: false - xy: 1045, 391 + xy: 1369, 876 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-arrow-16 rotate: false - xy: 1045, 391 + xy: 1369, 876 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-arrow-down rotate: false - xy: 1323, 1385 + xy: 333, 74 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-arrow-left rotate: false - xy: 1345, 1206 + xy: 1087, 1679 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-arrow-right rotate: false - xy: 777, 365 + xy: 568, 1949 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-arrow-up rotate: false - xy: 1173, 684 + xy: 1476, 863 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-back rotate: false - xy: 471, 637 + xy: 649, 1356 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-ban rotate: false - xy: 927, 377 + xy: 583, 1416 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-break rotate: false - xy: 489, 637 + xy: 295, 721 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-cancel rotate: false - xy: 1168, 160 + xy: 564, 1771 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-cancel-2 rotate: false - xy: 1999, 187 + xy: 528, 574 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 icon-chat rotate: false - xy: 1365, 591 + xy: 329, 2 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-check rotate: false - xy: 2031, 433 + xy: 299, 1218 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-check-2 rotate: false - xy: 1141, 108 + xy: 525, 548 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 icon-copy rotate: false - xy: 2031, 415 + xy: 1091, 1237 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-cursor rotate: false - xy: 961, 227 + xy: 989, 1663 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-database rotate: false - xy: 1641, 359 + xy: 1387, 946 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-database-small rotate: false - xy: 775, 77 + xy: 568, 1937 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-dev-builds rotate: false - xy: 1551, 797 + xy: 1523, 935 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-discord rotate: false - xy: 845, 971 + xy: 2033, 897 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-donate rotate: false - xy: 911, 427 + xy: 2027, 1151 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-dots rotate: false - xy: 2025, 161 + xy: 1019, 1463 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-editor rotate: false - xy: 2025, 641 + xy: 1035, 1463 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-egg rotate: false - xy: 535, 1084 + xy: 2033, 881 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-elevation rotate: false - xy: 845, 1543 + xy: 1840, 810 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-eraser rotate: false - xy: 845, 987 + xy: 633, 510 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-exit rotate: false - xy: 623, 907 + xy: 2033, 865 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-file rotate: false - xy: 527, 1543 + xy: 667, 1356 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-file-image rotate: false - xy: 893, 459 + xy: 1840, 792 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-file-text rotate: false - xy: 943, 377 + xy: 2033, 849 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-fill rotate: false - xy: 1109, 953 + xy: 633, 492 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-floppy rotate: false - xy: 1214, 162 + xy: 2033, 833 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-floppy-16 rotate: false - xy: 477, 1698 + xy: 633, 474 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-folder rotate: false - xy: 1993, 1199 + xy: 2033, 817 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-folder-parent rotate: false - xy: 959, 377 + xy: 313, 53 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-generated rotate: false - xy: 927, 393 + xy: 675, 1000 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 icon-github rotate: false - xy: 1434, 710 + xy: 625, 1218 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-google-play rotate: false - xy: 2032, 2033 + xy: 625, 1202 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-grid rotate: false - xy: 431, 27 + xy: 633, 456 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-hold rotate: false - xy: 2023, 587 + xy: 1476, 851 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-holdDelete rotate: false - xy: 845, 1071 + xy: 341, 2 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-home rotate: false - xy: 1229, 102 + xy: 1251, 973 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-host rotate: false - xy: 1247, 120 + xy: 1201, 923 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-info rotate: false - xy: 1434, 694 + xy: 1201, 907 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-itch.io rotate: false - xy: 2032, 2017 + xy: 2033, 801 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-item rotate: false - xy: 2031, 349 + xy: 568, 1925 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-items-none rotate: false - xy: 526, 1951 + xy: 1251, 963 size: 8, 8 orig: 8, 8 offset: 0, 0 index: -1 icon-line rotate: false - xy: 1897, 1345 + xy: 633, 438 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-link rotate: false - xy: 1229, 86 + xy: 303, 1418 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-liquid-small rotate: false - xy: 845, 1495 + xy: 353, 2 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-load rotate: false - xy: 1263, 120 + xy: 303, 1402 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-load-image rotate: false - xy: 1275, 585 + xy: 633, 402 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-load-map rotate: false - xy: 681, 139 + xy: 633, 384 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-loading rotate: false - xy: 571, 3 + xy: 633, 366 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-locked rotate: false - xy: 1267, 245 + xy: 633, 348 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-logic rotate: false - xy: 1109, 905 + xy: 365, 2 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-map rotate: false - xy: 2032, 2001 + xy: 303, 1386 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-menu rotate: false - xy: 1213, 1228 + xy: 377, 2 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-menu-large rotate: false - xy: 1991, 623 + xy: 633, 330 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-missing rotate: false - xy: 1323, 1373 + xy: 389, 2 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-mission-background rotate: false - xy: 845, 1083 + xy: 131, 711 size: 18, 18 orig: 18, 18 offset: 0, 0 index: -1 icon-mission-battle rotate: false - xy: 1345, 1194 + xy: 401, 2 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-mission-defense rotate: false - xy: 789, 365 + xy: 413, 2 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-mission-done rotate: false - xy: 973, 227 + xy: 425, 2 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-none rotate: false - xy: 787, 77 + xy: 437, 2 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-paste rotate: false - xy: 2025, 195 + xy: 633, 312 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-pause rotate: false - xy: 1323, 1361 + xy: 449, 2 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-pencil rotate: false - xy: 2021, 39 + xy: 633, 294 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-pencil-small rotate: false - xy: 1229, 70 + xy: 1352, 776 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-pick rotate: false - xy: 845, 1525 + xy: 633, 276 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-play rotate: false - xy: 985, 227 + xy: 461, 2 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-play-2 rotate: false - xy: 2032, 1985 + xy: 1984, 795 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-play-custom rotate: false - xy: 1229, 54 + xy: 2000, 795 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-players rotate: false - xy: 537, 165 + xy: 564, 1759 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-power-requirement rotate: false - xy: 1739, 485 + xy: 1471, 985 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 icon-power-small rotate: false - xy: 2035, 587 + xy: 1368, 758 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-quit rotate: false - xy: 2032, 1969 + xy: 2016, 795 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-redo rotate: false - xy: 1109, 935 + xy: 633, 222 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-refresh rotate: false - xy: 2032, 1953 + xy: 129, 9 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-rename rotate: false - xy: 1229, 38 + xy: 145, 9 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-resize rotate: false - xy: 495, 1698 + xy: 633, 204 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-rotate rotate: false - xy: 2021, 23 + xy: 161, 9 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-rotate-arrow rotate: false - xy: 2027, 941 + xy: 177, 9 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-rotate-left rotate: false - xy: 2027, 925 + xy: 193, 9 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-rotate-right rotate: false - xy: 2027, 909 + xy: 209, 9 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-save rotate: false - xy: 2027, 893 + xy: 299, 1202 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-save-image rotate: false - xy: 431, 9 + xy: 633, 186 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-save-map rotate: false - xy: 589, 3 + xy: 633, 168 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-settings rotate: false - xy: 1275, 671 + xy: 1858, 771 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-spray rotate: false - xy: 2025, 177 + xy: 633, 150 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-terrain rotate: false - xy: 845, 1507 + xy: 633, 132 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-tools rotate: false - xy: 2027, 877 + xy: 1930, 777 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-touch rotate: false - xy: 661, 9 + xy: 1870, 771 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-touchDelete rotate: false - xy: 1907, 1291 + xy: 1882, 771 size: 10, 10 orig: 10, 10 offset: 0, 0 index: -1 icon-trash rotate: false - xy: 2027, 861 + xy: 1946, 777 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-trash-16 rotate: false - xy: 1109, 917 + xy: 633, 114 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-tree rotate: false - xy: 607, 3 + xy: 633, 96 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-tree-locked rotate: false - xy: 1773, 519 + xy: 1505, 1019 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 icon-trello rotate: false - xy: 2027, 845 + xy: 1962, 777 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-tutorial rotate: false - xy: 2027, 829 + xy: 299, 1370 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-undo rotate: false - xy: 643, 3 + xy: 633, 60 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-unlocked rotate: false - xy: 455, 1000 + xy: 633, 24 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-unlocks rotate: false - xy: 2027, 813 + xy: 1352, 760 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-wiki rotate: false - xy: 2027, 797 + xy: 1368, 770 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 icon-zone rotate: false - xy: 1141, 82 + xy: 525, 522 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 icon-zone-locked rotate: false - xy: 1907, 1197 + xy: 87, 37 size: 42, 42 orig: 42, 42 offset: 0, 0 index: -1 icon-zoom rotate: false - xy: 491, 1000 + xy: 633, 6 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 icon-zoom-small rotate: false - xy: 1337, 710 + xy: 1349, 744 size: 14, 14 orig: 14, 14 offset: 0, 0 index: -1 info-banner rotate: false - xy: 1237, 1350 + xy: 611, 1416 size: 84, 45 orig: 84, 45 offset: 0, 0 index: -1 inventory rotate: false - xy: 2023, 599 + xy: 529, 402 size: 24, 40 split: 10, 10, 10, 14 orig: 24, 40 @@ -9523,7 +7367,7 @@ logotext index: -1 pane rotate: false - xy: 2003, 1410 + xy: 1325, 1068 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -9531,7 +7375,7 @@ pane index: -1 pane-2 rotate: false - xy: 2003, 1439 + xy: 261, 1372 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -9539,7 +7383,7 @@ pane-2 index: -1 scroll rotate: false - xy: 1683, 72 + xy: 555, 59 size: 24, 35 split: 10, 10, 6, 5 orig: 24, 35 @@ -9547,7 +7391,7 @@ scroll index: -1 scroll-horizontal rotate: false - xy: 1261, 683 + xy: 2012, 2023 size: 35, 24 split: 6, 5, 10, 10 orig: 35, 24 @@ -9555,7 +7399,7 @@ scroll-horizontal index: -1 scroll-knob-horizontal-black rotate: false - xy: 1151, 888 + xy: 253, 713 size: 40, 24 split: 11, 10, 10, 10 orig: 40, 24 @@ -9563,7 +7407,7 @@ scroll-knob-horizontal-black index: -1 scroll-knob-vertical-black rotate: false - xy: 1657, 67 + xy: 555, 96 size: 24, 40 split: 10, 10, 6, 10 orig: 24, 40 @@ -9571,56 +7415,56 @@ scroll-knob-vertical-black index: -1 sector-select rotate: false - xy: 1335, 318 + xy: 1795, 862 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 selection rotate: false - xy: 1433, 587 + xy: 530, 693 size: 1, 1 orig: 1, 1 offset: 0, 0 index: -1 slider rotate: false - xy: 1136, 160 + xy: 1395, 802 size: 1, 8 orig: 1, 8 offset: 0, 0 index: -1 slider-knob rotate: false - xy: 1139, 198 + xy: 499, 656 size: 29, 38 orig: 29, 38 offset: 0, 0 index: -1 slider-knob-down rotate: false - xy: 1105, 130 + xy: 499, 616 size: 29, 38 orig: 29, 38 offset: 0, 0 index: -1 slider-knob-over rotate: false - xy: 1105, 130 + xy: 499, 616 size: 29, 38 orig: 29, 38 offset: 0, 0 index: -1 slider-vertical rotate: false - xy: 837, 675 + xy: 87, 34 size: 8, 1 orig: 8, 1 offset: 0, 0 index: -1 underline rotate: false - xy: 1223, 680 + xy: 1075, 768 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -9628,7 +7472,7 @@ underline index: -1 underline-2 rotate: false - xy: 1185, 680 + xy: 1355, 1030 size: 36, 27 split: 12, 12, 12, 12 orig: 36, 27 @@ -9636,14 +7480,14 @@ underline-2 index: -1 white rotate: false - xy: 1369, 1284 + xy: 691, 1200 size: 3, 3 orig: 3, 3 offset: 0, 0 index: -1 window-empty rotate: false - xy: 1320, 187 + xy: 1369, 812 size: 27, 61 split: 8, 8, 44, 11 orig: 27, 61 @@ -9651,161 +7495,161 @@ window-empty index: -1 chaos-array rotate: false - xy: 786, 1821 + xy: 582, 1919 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 chaos-array-base rotate: false - xy: 916, 1821 + xy: 712, 1919 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 chaos-array-leg rotate: false - xy: 1046, 1821 + xy: 842, 1919 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 crawler rotate: false - xy: 1657, 1247 + xy: 345, 414 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 crawler-base rotate: false - xy: 1707, 1247 + xy: 395, 464 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 crawler-leg rotate: false - xy: 1757, 1247 + xy: 395, 414 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 dagger rotate: false - xy: 1407, 1189 + xy: 395, 314 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 dagger-base rotate: false - xy: 1457, 1189 + xy: 345, 214 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 dagger-leg rotate: false - xy: 1557, 1197 + xy: 345, 164 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 eradicator rotate: false - xy: 323, 1632 + xy: 1, 1109 size: 152, 124 orig: 152, 124 offset: 0, 0 index: -1 eradicator-base rotate: false - xy: 291, 367 + xy: 1, 983 size: 152, 124 orig: 152, 124 offset: 0, 0 index: -1 eradicator-leg rotate: false - xy: 323, 1506 + xy: 1, 857 size: 152, 124 orig: 152, 124 offset: 0, 0 index: -1 eruptor rotate: false - xy: 799, 1005 + xy: 1447, 1429 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 eruptor-base rotate: false - xy: 779, 939 + xy: 1513, 1429 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 eruptor-leg rotate: false - xy: 1937, 1407 + xy: 1579, 1429 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 fortress rotate: false - xy: 865, 1037 + xy: 1645, 1429 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 fortress-base rotate: false - xy: 931, 1037 + xy: 1711, 1429 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 titan-base rotate: false - xy: 931, 1037 + xy: 1711, 1429 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 fortress-leg rotate: false - xy: 997, 1037 + xy: 1777, 1429 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 ghoul rotate: false - xy: 1956, 1877 + xy: 1956, 1845 size: 72, 72 orig: 72, 72 offset: 0, 0 index: -1 lich rotate: false - xy: 291, 655 + xy: 1, 1397 size: 216, 240 orig: 216, 240 offset: 0, 0 index: -1 phantom rotate: false - xy: 513, 1 + xy: 517, 822 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 power-cell rotate: false - xy: 577, 415 + xy: 516, 764 size: 56, 56 orig: 56, 56 offset: 0, 0 @@ -9819,148 +7663,2918 @@ reaper index: -1 revenant rotate: false - xy: 323, 1002 + xy: 973, 1675 size: 112, 112 orig: 112, 112 offset: 0, 0 index: -1 spirit rotate: false - xy: 1151, 838 + xy: 975, 831 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 titan rotate: false - xy: 837, 773 + xy: 319, 1168 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 titan-leg rotate: false - xy: 903, 839 + xy: 319, 1102 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 wraith rotate: false - xy: 1551, 647 + xy: 1225, 1031 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 artillery-equip rotate: false - xy: 611, 307 + xy: 295, 448 size: 48, 56 orig: 48, 56 offset: 0, 0 index: -1 blaster-equip rotate: false - xy: 793, 427 + xy: 295, 198 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 bomber-equip rotate: false - xy: 843, 427 + xy: 295, 148 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 missiles-equip rotate: false - xy: 843, 427 + xy: 295, 148 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 chain-blaster-equip rotate: false - xy: 603, 207 + xy: 399, 614 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 chaos-equip rotate: false - xy: 1077, 569 + xy: 525, 1228 size: 56, 136 orig: 56, 136 offset: 0, 0 index: -1 eradication-equip rotate: false - xy: 453, 1312 + xy: 317, 1434 size: 96, 192 orig: 96, 192 offset: 0, 0 index: -1 eruption-equip rotate: false - xy: 1387, 1076 + xy: 575, 970 size: 48, 56 orig: 48, 56 offset: 0, 0 index: -1 flakgun-equip rotate: false - xy: 1387, 1026 + xy: 575, 920 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 flamethrower-equip rotate: false - xy: 727, 365 + xy: 575, 862 size: 48, 56 orig: 48, 56 offset: 0, 0 index: -1 heal-blaster-equip rotate: false - xy: 761, 265 + xy: 625, 850 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 lich-missiles-equip rotate: false - xy: 1895, 1147 + xy: 445, 122 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 reaper-gun-equip rotate: false - xy: 1577, 847 + xy: 825, 789 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 revenant-missiles-equip rotate: false - xy: 1677, 897 + xy: 824, 739 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 shockgun-equip rotate: false - xy: 1827, 797 + xy: 975, 981 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 swarmer-equip rotate: false - xy: 1401, 776 + xy: 974, 731 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 + +sprites2.png +size: 2048,512 +format: RGBA8888 +filter: Nearest,Nearest +repeat: none +alloy-smelter-icon-editor + rotate: false + xy: 905, 269 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +alpha-dart-mech-pad-icon-editor + rotate: false + xy: 1395, 333 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +arc-icon-editor + rotate: false + xy: 2015, 463 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +battery-icon-editor + rotate: false + xy: 2015, 429 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +battery-large-icon-editor + rotate: false + xy: 1035, 399 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +blast-drill-icon-editor + rotate: false + xy: 645, 367 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +blast-mixer-icon-editor + rotate: false + xy: 1461, 333 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +block-border-editor + rotate: false + xy: 2015, 395 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +bridge-conduit-icon-editor + rotate: false + xy: 1819, 191 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +bridge-conveyor-icon-editor + rotate: false + xy: 1861, 233 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +char-icon-editor + rotate: false + xy: 1895, 233 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-char1 + rotate: false + xy: 1895, 233 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +clear-editor + rotate: false + xy: 645, 234 + size: 1, 1 + orig: 1, 1 + offset: 0, 0 + index: -1 +cliffs-icon-editor + rotate: false + xy: 1929, 233 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +combustion-generator-icon-editor + rotate: false + xy: 945, 39 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conduit-icon-editor + rotate: false + xy: 979, 39 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +container-icon-editor + rotate: false + xy: 1527, 333 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +conveyor-icon-editor + rotate: false + xy: 1109, 69 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +copper-wall-icon-editor + rotate: false + xy: 1143, 69 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +copper-wall-large-icon-editor + rotate: false + xy: 1593, 333 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +core-foundation-icon-editor + rotate: false + xy: 163, 45 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +core-nucleus-icon-editor + rotate: false + xy: 1, 13 + size: 160, 160 + orig: 160, 160 + offset: 0, 0 + index: -1 +core-shard-icon-editor + rotate: false + xy: 1133, 399 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +craters-icon-editor + rotate: false + xy: 1177, 69 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-craters1 + rotate: false + xy: 1177, 69 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +crawler-factory-icon-editor + rotate: false + xy: 1659, 333 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +cryofluidmixer-icon-editor + rotate: false + xy: 1725, 333 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +cultivator-icon-editor + rotate: false + xy: 1791, 333 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +cyclone-icon-editor + rotate: false + xy: 1231, 399 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +dagger-factory-icon-editor + rotate: false + xy: 1857, 333 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +deepwater-icon-editor + rotate: false + xy: 1211, 69 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-deepwater + rotate: false + xy: 1211, 69 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +delta-mech-pad-icon-editor + rotate: false + xy: 1923, 333 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +differential-generator-icon-editor + rotate: false + xy: 1329, 399 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +distributor-icon-editor + rotate: false + xy: 1043, 203 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +door-icon-editor + rotate: false + xy: 1245, 69 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +door-large-icon-editor + rotate: false + xy: 1043, 137 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +dunerocks-icon-editor + rotate: false + xy: 1279, 69 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +duo-icon-editor + rotate: false + xy: 1313, 69 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-char2 + rotate: false + xy: 163, 11 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-char3 + rotate: false + xy: 197, 11 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-clear + rotate: false + xy: 1803, 155 + size: 10, 10 + orig: 10, 10 + offset: 0, 0 + index: -1 +editor-craters2 + rotate: false + xy: 231, 11 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-craters3 + rotate: false + xy: 265, 11 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-craters4 + rotate: false + xy: 299, 11 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-craters5 + rotate: false + xy: 333, 11 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-stone1 + rotate: false + xy: 333, 11 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stone-icon-editor + rotate: false + xy: 333, 11 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-craters6 + rotate: false + xy: 367, 11 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-stone2 + rotate: false + xy: 367, 11 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-grass1 + rotate: false + xy: 401, 11 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +grass-icon-editor + rotate: false + xy: 401, 11 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-grass2 + rotate: false + xy: 435, 11 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-grass3 + rotate: false + xy: 469, 11 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-holostone1 + rotate: false + xy: 503, 11 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +holostone-icon-editor + rotate: false + xy: 503, 11 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-holostone2 + rotate: false + xy: 1373, 101 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-holostone3 + rotate: false + xy: 1407, 101 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-hotrock1 + rotate: false + xy: 1441, 101 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +hotrock-icon-editor + rotate: false + xy: 1441, 101 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-hotrock2 + rotate: false + xy: 1475, 101 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-hotrock3 + rotate: false + xy: 1509, 101 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ice-snow1 + rotate: false + xy: 1645, 101 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ice-snow-icon-editor + rotate: false + xy: 1645, 101 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ice-snow2 + rotate: false + xy: 1679, 101 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ice-snow3 + rotate: false + xy: 1713, 101 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ice1 + rotate: false + xy: 1543, 101 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ice-icon-editor + rotate: false + xy: 1543, 101 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ice2 + rotate: false + xy: 1577, 101 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ice3 + rotate: false + xy: 1611, 101 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ignarock1 + rotate: false + xy: 1769, 133 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ignarock-icon-editor + rotate: false + xy: 1769, 133 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ignarock2 + rotate: false + xy: 1963, 233 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ignarock3 + rotate: false + xy: 1819, 157 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-magmarock1 + rotate: false + xy: 1747, 99 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +magmarock-icon-editor + rotate: false + xy: 1747, 99 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-magmarock2 + rotate: false + xy: 1781, 99 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-magmarock3 + rotate: false + xy: 1853, 191 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-metal-floor + rotate: false + xy: 1853, 157 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-metal-floor-damaged5 + rotate: false + xy: 1853, 157 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-icon-editor + rotate: false + xy: 1853, 157 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-metal-floor-2 + rotate: false + xy: 1887, 199 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-2-icon-editor + rotate: false + xy: 1887, 199 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-metal-floor-3 + rotate: false + xy: 1887, 165 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-3-icon-editor + rotate: false + xy: 1887, 165 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-metal-floor-5 + rotate: false + xy: 1921, 199 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-5-icon-editor + rotate: false + xy: 1921, 199 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-metal-floor-damaged1 + rotate: false + xy: 1921, 165 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-damaged-icon-editor + rotate: false + xy: 1921, 165 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-metal-floor-damaged2 + rotate: false + xy: 1955, 199 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-metal-floor-damaged3 + rotate: false + xy: 1955, 165 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-metal-floor-damaged4 + rotate: false + xy: 1989, 361 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-metal-floor-damaged6 + rotate: false + xy: 1989, 327 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-moss1 + rotate: false + xy: 1989, 293 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +moss-icon-editor + rotate: false + xy: 1989, 293 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-moss2 + rotate: false + xy: 1887, 131 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-moss3 + rotate: false + xy: 1921, 131 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-coal1 + rotate: false + xy: 1955, 131 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-coal2 + rotate: false + xy: 1989, 199 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-coal3 + rotate: false + xy: 1989, 165 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-copper1 + rotate: false + xy: 1989, 131 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-copper2 + rotate: false + xy: 1347, 67 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-copper3 + rotate: false + xy: 1381, 67 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-lead1 + rotate: false + xy: 1415, 67 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-lead2 + rotate: false + xy: 1449, 67 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-lead3 + rotate: false + xy: 1483, 67 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-scrap1 + rotate: false + xy: 1517, 67 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-scrap2 + rotate: false + xy: 1551, 67 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-scrap3 + rotate: false + xy: 1585, 67 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-thorium1 + rotate: false + xy: 1619, 67 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-thorium2 + rotate: false + xy: 1653, 67 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-thorium3 + rotate: false + xy: 1687, 67 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-titanium1 + rotate: false + xy: 1815, 123 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-titanium2 + rotate: false + xy: 1849, 123 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-ore-titanium3 + rotate: false + xy: 1815, 89 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-salt + rotate: false + xy: 1849, 89 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +salt-icon-editor + rotate: false + xy: 1849, 89 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-sand-water + rotate: false + xy: 1985, 97 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sand-water-icon-editor + rotate: false + xy: 1985, 97 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-sand1 + rotate: false + xy: 1883, 97 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sand-icon-editor + rotate: false + xy: 1883, 97 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-sand2 + rotate: false + xy: 1917, 97 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-sand3 + rotate: false + xy: 1951, 97 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-shale1 + rotate: false + xy: 1883, 63 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +shale-icon-editor + rotate: false + xy: 1883, 63 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-shale2 + rotate: false + xy: 1917, 63 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-shale3 + rotate: false + xy: 1951, 63 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-snow1 + rotate: false + xy: 1985, 63 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +snow-icon-editor + rotate: false + xy: 1985, 63 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-snow2 + rotate: false + xy: 1721, 65 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-snow3 + rotate: false + xy: 1755, 65 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-spore-moss1 + rotate: false + xy: 1013, 37 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spore-moss-icon-editor + rotate: false + xy: 1013, 37 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-spore-moss2 + rotate: false + xy: 1047, 37 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-spore-moss3 + rotate: false + xy: 1081, 35 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-stone3 + rotate: false + xy: 1115, 35 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-tar + rotate: false + xy: 1149, 35 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +tar-icon-editor + rotate: false + xy: 1149, 35 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +editor-water + rotate: false + xy: 1183, 35 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +water-icon-editor + rotate: false + xy: 1183, 35 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +force-projector-icon-editor + rotate: false + xy: 1427, 399 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +fortress-factory-icon-editor + rotate: false + xy: 1525, 399 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +fuse-icon-editor + rotate: false + xy: 1623, 399 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +ghoul-factory-icon-editor + rotate: false + xy: 1721, 399 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +glaive-ship-pad-icon-editor + rotate: false + xy: 1819, 399 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +graphite-press-icon-editor + rotate: false + xy: 1043, 71 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +hail-icon-editor + rotate: false + xy: 1217, 35 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icerocks-icon-editor + rotate: false + xy: 1251, 35 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +impact-reactor-icon-editor + rotate: false + xy: 645, 237 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +incinerator-icon-editor + rotate: false + xy: 1285, 35 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-source-icon-editor + rotate: false + xy: 1319, 33 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-void-icon-editor + rotate: false + xy: 1353, 33 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +javelin-ship-pad-icon-editor + rotate: false + xy: 1109, 235 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +junction-icon-editor + rotate: false + xy: 1387, 33 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +kiln-icon-editor + rotate: false + xy: 1109, 169 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +lancer-icon-editor + rotate: false + xy: 1175, 235 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +laser-drill-icon-editor + rotate: false + xy: 1917, 399 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +launch-pad-icon-editor + rotate: false + xy: 553, 77 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +liquid-junction-icon-editor + rotate: false + xy: 1421, 33 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-router-icon-editor + rotate: false + xy: 1455, 33 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-source-icon-editor + rotate: false + xy: 1489, 33 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-tank-icon-editor + rotate: false + xy: 651, 139 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +mass-driver-icon-editor + rotate: false + xy: 749, 139 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +mechanical-drill-icon-editor + rotate: false + xy: 1109, 103 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +mechanical-pump-icon-editor + rotate: false + xy: 1523, 33 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +meltdown-icon-editor + rotate: false + xy: 775, 367 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +melter-icon-editor + rotate: false + xy: 1557, 33 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +mend-projector-icon-editor + rotate: false + xy: 1175, 169 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +multi-press-icon-editor + rotate: false + xy: 651, 41 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +oil-extractor-icon-editor + rotate: false + xy: 749, 41 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +omega-mech-pad-icon-editor + rotate: false + xy: 847, 139 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +overdrive-projector-icon-editor + rotate: false + xy: 1241, 235 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +overflow-gate-icon-editor + rotate: false + xy: 1591, 33 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phantom-factory-icon-editor + rotate: false + xy: 1175, 103 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +phase-conduit-icon-editor + rotate: false + xy: 1625, 33 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-conveyor-icon-editor + rotate: false + xy: 1659, 33 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-wall-icon-editor + rotate: false + xy: 1693, 31 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-wall-large-icon-editor + rotate: false + xy: 1241, 169 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +phase-weaver-icon-editor + rotate: false + xy: 1307, 235 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +pine-icon-editor + rotate: false + xy: 1769, 217 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +plastanium-compressor-icon-editor + rotate: false + xy: 1241, 103 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +pneumatic-drill-icon-editor + rotate: false + xy: 1307, 169 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +power-node-icon-editor + rotate: false + xy: 1727, 31 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +power-node-large-icon-editor + rotate: false + xy: 1307, 103 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +power-source-icon-editor + rotate: false + xy: 1761, 31 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +power-void-icon-editor + rotate: false + xy: 1997, 259 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pulse-conduit-icon-editor + rotate: false + xy: 619, 7 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pulverizer-icon-editor + rotate: false + xy: 653, 7 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pyratite-mixer-icon-editor + rotate: false + xy: 553, 11 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +repair-point-icon-editor + rotate: false + xy: 687, 7 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +revenant-factory-icon-editor + rotate: false + xy: 293, 45 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +ripple-icon-editor + rotate: false + xy: 847, 41 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +rocks-icon-editor + rotate: false + xy: 721, 7 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +rotary-pump-icon-editor + rotate: false + xy: 1395, 267 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +router-icon-editor + rotate: false + xy: 755, 7 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +rtg-generator-icon-editor + rotate: false + xy: 1461, 267 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +salvo-icon-editor + rotate: false + xy: 1527, 267 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +sandrocks-icon-editor + rotate: false + xy: 789, 7 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scatter-icon-editor + rotate: false + xy: 1593, 267 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +scrap-wall-gigantic-icon-editor + rotate: false + xy: 775, 237 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +scrap-wall-huge-icon-editor + rotate: false + xy: 1003, 269 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +scrap-wall-icon-editor + rotate: false + xy: 823, 7 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap-wall-large-icon-editor + rotate: false + xy: 1659, 267 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +separator-icon-editor + rotate: false + xy: 1725, 267 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +shale-boulder-icon-editor + rotate: false + xy: 857, 7 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +shalerocks-icon-editor + rotate: false + xy: 891, 7 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +shock-mine-icon-editor + rotate: false + xy: 925, 5 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +silicon-smelter-icon-editor + rotate: false + xy: 1791, 267 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +snowrocks-icon-editor + rotate: false + xy: 959, 5 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +solar-panel-icon-editor + rotate: false + xy: 993, 3 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +solar-panel-large-icon-editor + rotate: false + xy: 945, 171 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +sorter-icon-editor + rotate: false + xy: 1027, 3 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spawn-icon-editor + rotate: false + xy: 1061, 1 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spectre-icon-editor + rotate: false + xy: 905, 367 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +spirit-factory-icon-editor + rotate: false + xy: 1857, 267 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +spore-cluster-icon-editor + rotate: false + xy: 1819, 225 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +spore-pine-icon-editor + rotate: false + xy: 1769, 167 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +spore-press-icon-editor + rotate: false + xy: 1923, 267 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +surge-tower-icon-editor + rotate: false + xy: 1373, 201 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +surge-wall-icon-editor + rotate: false + xy: 1095, 1 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +surge-wall-large-icon-editor + rotate: false + xy: 1373, 135 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +swarmer-icon-editor + rotate: false + xy: 1439, 201 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +tau-mech-pad-icon-editor + rotate: false + xy: 1439, 135 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +thermal-generator-icon-editor + rotate: false + xy: 1505, 201 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +thermal-pump-icon-editor + rotate: false + xy: 945, 73 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +thorium-reactor-icon-editor + rotate: false + xy: 1101, 301 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +thorium-wall-icon-editor + rotate: false + xy: 1129, 1 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +thorium-wall-large-icon-editor + rotate: false + xy: 1505, 135 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +thruster-icon-editor + rotate: false + xy: 423, 45 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +titan-factory-icon-editor + rotate: false + xy: 1199, 301 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +titanium-conveyor-icon-editor + rotate: false + xy: 1163, 1 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium-wall-icon-editor + rotate: false + xy: 1197, 1 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium-wall-large-icon-editor + rotate: false + xy: 1571, 201 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +trident-ship-pad-icon-editor + rotate: false + xy: 1571, 135 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +turbine-generator-icon-editor + rotate: false + xy: 1637, 201 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +unloader-icon-editor + rotate: false + xy: 1231, 1 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +vault-icon-editor + rotate: false + xy: 1297, 301 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +water-extractor-icon-editor + rotate: false + xy: 1637, 135 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +wave-icon-editor + rotate: false + xy: 1703, 201 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +white-tree-dead-icon-editor + rotate: false + xy: 1, 175 + size: 320, 320 + orig: 320, 320 + offset: 0, 0 + index: -1 +white-tree-icon-editor + rotate: false + xy: 323, 175 + size: 320, 320 + orig: 320, 320 + offset: 0, 0 + index: -1 +wraith-factory-icon-editor + rotate: false + xy: 1703, 135 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 + +sprites3.png +size: 2048,1024 +format: RGBA8888 +filter: Nearest,Nearest +repeat: none +char1 + rotate: false + xy: 1549, 793 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +char2 + rotate: false + xy: 373, 401 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +char3 + rotate: false + xy: 117, 51 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +cliffs1 + rotate: false + xy: 1773, 873 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +coal1 + rotate: false + xy: 1889, 989 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +coal2 + rotate: false + xy: 721, 499 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +coal3 + rotate: false + xy: 1011, 597 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +copper1 + rotate: false + xy: 1301, 695 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +copper2 + rotate: false + xy: 1583, 793 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +copper3 + rotate: false + xy: 407, 401 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +craters1 + rotate: false + xy: 151, 51 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +craters2 + rotate: false + xy: 1773, 839 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +craters3 + rotate: false + xy: 1923, 989 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +craters4 + rotate: false + xy: 755, 499 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +craters5 + rotate: false + xy: 1045, 597 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stone1 + rotate: false + xy: 1045, 597 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +craters6 + rotate: false + xy: 1335, 695 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stone2 + rotate: false + xy: 1335, 695 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +deepwater + rotate: false + xy: 1617, 793 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +deepwater-edge + rotate: false + xy: 323, 925 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +dunerocks-large + rotate: false + xy: 1, 19 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +dunerocks1 + rotate: false + xy: 441, 401 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dunerocks2 + rotate: false + xy: 185, 51 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +edge-stencil-blocky + rotate: false + xy: 1, 281 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +edge-stencil-smooth + rotate: false + xy: 323, 827 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +grass-edge + rotate: false + xy: 613, 925 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +grass1 + rotate: false + xy: 1957, 989 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +grass2 + rotate: false + xy: 789, 499 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +grass3 + rotate: false + xy: 1079, 597 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +holostone-edge + rotate: false + xy: 1, 183 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +holostone1 + rotate: false + xy: 1369, 695 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +holostone2 + rotate: false + xy: 1651, 793 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +holostone3 + rotate: false + xy: 475, 401 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +hotrock1 + rotate: false + xy: 219, 51 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +hotrock2 + rotate: false + xy: 1991, 989 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +hotrock3 + rotate: false + xy: 823, 499 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ice-edge + rotate: false + xy: 323, 729 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +ice-snow-edge + rotate: false + xy: 613, 827 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +ice-snow1 + rotate: false + xy: 509, 401 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ice-snow2 + rotate: false + xy: 253, 51 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ice-snow3 + rotate: false + xy: 857, 499 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ice1 + rotate: false + xy: 1113, 597 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ice2 + rotate: false + xy: 1403, 695 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ice3 + rotate: false + xy: 1685, 793 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icerocks-large + rotate: false + xy: 1773, 957 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +icerocks1 + rotate: false + xy: 1147, 597 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icerocks2 + rotate: false + xy: 1437, 695 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ignarock-edge + rotate: false + xy: 903, 925 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +ignarock1 + rotate: false + xy: 1719, 793 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ignarock2 + rotate: false + xy: 543, 401 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ignarock3 + rotate: false + xy: 577, 401 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +lead1 + rotate: false + xy: 291, 345 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +lead2 + rotate: false + xy: 291, 311 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +lead3 + rotate: false + xy: 291, 277 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +magmarock1 + rotate: false + xy: 291, 243 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +magmarock2 + rotate: false + xy: 291, 209 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +magmarock3 + rotate: false + xy: 291, 175 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor + rotate: false + xy: 291, 141 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-damaged5 + rotate: false + xy: 291, 141 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-2 + rotate: false + xy: 291, 107 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-2-edge + rotate: false + xy: 1, 85 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +metal-floor-3 + rotate: false + xy: 613, 433 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-3-edge + rotate: false + xy: 323, 631 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +metal-floor-5 + rotate: false + xy: 903, 531 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-5-edge + rotate: false + xy: 613, 729 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +metal-floor-damaged-edge + rotate: false + xy: 903, 827 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +metal-floor-damaged1 + rotate: false + xy: 1193, 629 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-damaged2 + rotate: false + xy: 1483, 727 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-damaged3 + rotate: false + xy: 1549, 759 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-damaged4 + rotate: false + xy: 1583, 759 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-damaged6 + rotate: false + xy: 1617, 759 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-edge + rotate: false + xy: 1193, 925 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +moss-edge + rotate: false + xy: 323, 533 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +moss1 + rotate: false + xy: 1651, 759 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +moss2 + rotate: false + xy: 1685, 759 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +moss3 + rotate: false + xy: 1719, 759 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal1 + rotate: false + xy: 647, 433 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal2 + rotate: false + xy: 937, 531 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-coal3 + rotate: false + xy: 1227, 629 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper1 + rotate: false + xy: 611, 399 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper2 + rotate: false + xy: 645, 399 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-copper3 + rotate: false + xy: 325, 351 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead1 + rotate: false + xy: 325, 317 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead2 + rotate: false + xy: 325, 283 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-lead3 + rotate: false + xy: 325, 249 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap1 + rotate: false + xy: 325, 215 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap2 + rotate: false + xy: 325, 181 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-scrap3 + rotate: false + xy: 325, 147 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium1 + rotate: false + xy: 325, 113 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium2 + rotate: false + xy: 291, 73 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-thorium3 + rotate: false + xy: 325, 79 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium1 + rotate: false + xy: 1753, 793 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium2 + rotate: false + xy: 1753, 759 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ore-titanium3 + rotate: false + xy: 891, 497 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pine + rotate: false + xy: 323, 385 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +rock1 + rotate: false + xy: 67, 35 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +rock2 + rotate: false + xy: 1773, 907 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +rocks-large + rotate: false + xy: 613, 467 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +rocks1 + rotate: false + xy: 925, 497 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +rocks2 + rotate: false + xy: 1181, 595 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +salt + rotate: false + xy: 1215, 595 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +salt-edge + rotate: false + xy: 613, 631 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +sand-edge + rotate: false + xy: 903, 729 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +sand-water + rotate: false + xy: 1823, 923 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sand-water-edge + rotate: false + xy: 1193, 827 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +sand1 + rotate: false + xy: 1471, 693 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sand2 + rotate: false + xy: 287, 39 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sand3 + rotate: false + xy: 67, 1 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sandrocks-large + rotate: false + xy: 903, 565 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +sandrocks1 + rotate: false + xy: 1807, 873 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sandrocks2 + rotate: false + xy: 1807, 839 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap1 + rotate: false + xy: 1787, 805 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap2 + rotate: false + xy: 1787, 771 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap3 + rotate: false + xy: 1821, 805 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +shale-boulder1 + rotate: false + xy: 1957, 955 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +shale-boulder2 + rotate: false + xy: 1991, 955 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +shale-edge + rotate: false + xy: 1483, 925 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +shale1 + rotate: false + xy: 1821, 771 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +shale2 + rotate: false + xy: 1889, 955 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +shale3 + rotate: false + xy: 1923, 955 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +shalerocks-large + rotate: false + xy: 1193, 663 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +shalerocks1 + rotate: false + xy: 373, 367 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +shalerocks2 + rotate: false + xy: 407, 367 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +snow-edge + rotate: false + xy: 323, 435 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +snow1 + rotate: false + xy: 441, 367 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +snow2 + rotate: false + xy: 475, 367 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +snow3 + rotate: false + xy: 509, 367 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +snowrocks-large + rotate: false + xy: 1483, 761 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +snowrocks1 + rotate: false + xy: 543, 367 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +snowrocks2 + rotate: false + xy: 577, 367 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spore-cluster1 + rotate: false + xy: 679, 491 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +spore-cluster2 + rotate: false + xy: 969, 589 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +spore-cluster3 + rotate: false + xy: 1259, 687 + size: 40, 40 + orig: 40, 40 + offset: 0, 0 + index: -1 +spore-moss-edge + rotate: false + xy: 613, 533 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +spore-moss1 + rotate: false + xy: 611, 365 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spore-moss2 + rotate: false + xy: 645, 365 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spore-moss3 + rotate: false + xy: 359, 333 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spore-pine + rotate: false + xy: 1839, 973 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +stone-edge + rotate: false + xy: 903, 631 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +stone3 + rotate: false + xy: 359, 299 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +tar + rotate: false + xy: 393, 333 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +tar-edge + rotate: false + xy: 1193, 729 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +thorium1 + rotate: false + xy: 359, 265 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +thorium2 + rotate: false + xy: 393, 299 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +thorium3 + rotate: false + xy: 427, 333 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium1 + rotate: false + xy: 359, 231 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium2 + rotate: false + xy: 393, 265 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium3 + rotate: false + xy: 427, 299 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +water + rotate: false + xy: 461, 333 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +water-edge + rotate: false + xy: 1483, 827 + size: 288, 96 + orig: 288, 96 + offset: 0, 0 + index: -1 +white-tree + rotate: false + xy: 1, 701 + size: 320, 320 + orig: 320, 320 + offset: 0, 0 + index: -1 +white-tree-dead + rotate: false + xy: 1, 379 + size: 320, 320 + orig: 320, 320 + offset: 0, 0 + index: -1 diff --git a/core/assets/sprites/sprites.png b/core/assets/sprites/sprites.png index bdbb2fe918..f04b623bb2 100644 Binary files a/core/assets/sprites/sprites.png and b/core/assets/sprites/sprites.png differ diff --git a/core/assets/sprites/sprites2.png b/core/assets/sprites/sprites2.png new file mode 100644 index 0000000000..5f90253ca5 Binary files /dev/null and b/core/assets/sprites/sprites2.png differ diff --git a/core/assets/sprites/sprites3.png b/core/assets/sprites/sprites3.png new file mode 100644 index 0000000000..8102b5b089 Binary files /dev/null and b/core/assets/sprites/sprites3.png differ diff --git a/core/src/io/anuke/mindustry/Mindustry.java b/core/src/io/anuke/mindustry/Mindustry.java index c4a571ef1e..44840a9aa4 100644 --- a/core/src/io/anuke/mindustry/Mindustry.java +++ b/core/src/io/anuke/mindustry/Mindustry.java @@ -17,7 +17,7 @@ public class Mindustry extends ApplicationCore{ public void setup(){ Time.setDeltaProvider(() -> { float result = Core.graphics.getDeltaTime() * 60f; - return Float.isNaN(result) || Float.isInfinite(result) ? 1f : Math.min(result, 60f / 10f); + return (Float.isNaN(result) || Float.isInfinite(result)) ? 1f : Math.min(result, 60f / 10f); }); Time.mark(); diff --git a/core/src/io/anuke/mindustry/Vars.java b/core/src/io/anuke/mindustry/Vars.java index 51e9bae7b5..43324c873a 100644 --- a/core/src/io/anuke/mindustry/Vars.java +++ b/core/src/io/anuke/mindustry/Vars.java @@ -2,21 +2,21 @@ package io.anuke.mindustry; import io.anuke.arc.Application.ApplicationType; import io.anuke.arc.Core; -import io.anuke.mindustry.entities.Entities; -import io.anuke.mindustry.entities.EntityGroup; -import io.anuke.mindustry.entities.impl.EffectEntity; -import io.anuke.mindustry.entities.traits.DrawTrait; import io.anuke.arc.files.FileHandle; import io.anuke.arc.graphics.Color; import io.anuke.arc.util.Structs; import io.anuke.mindustry.core.*; -import io.anuke.mindustry.entities.type.Player; -import io.anuke.mindustry.entities.type.TileEntity; +import io.anuke.mindustry.entities.Entities; +import io.anuke.mindustry.entities.EntityGroup; import io.anuke.mindustry.entities.bullet.Bullet; import io.anuke.mindustry.entities.effect.Fire; import io.anuke.mindustry.entities.effect.Puddle; +import io.anuke.mindustry.entities.impl.EffectEntity; +import io.anuke.mindustry.entities.traits.DrawTrait; import io.anuke.mindustry.entities.traits.SyncTrait; import io.anuke.mindustry.entities.type.BaseUnit; +import io.anuke.mindustry.entities.type.Player; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.game.GlobalData; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.game.Version; @@ -24,11 +24,16 @@ import io.anuke.mindustry.gen.Serialization; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.world.blocks.defense.ForceProjector.ShieldEntity; +import java.nio.charset.Charset; import java.util.Arrays; import java.util.Locale; @SuppressWarnings("unchecked") public class Vars{ + /**IO buffer size.*/ + public static final int bufferSize = 8192; + /**global charset*/ + public static final Charset charset = Charset.forName("UTF-8"); /**main application name, capitalized*/ public static final String appName = "Mindustry"; /**URL for discord invite.*/ @@ -156,6 +161,9 @@ public class Vars{ Version.init(); content = new ContentLoader(); + if(!headless){ + content.setVerbose(); + } playerGroup = Entities.addGroup(Player.class).enableMapping(); tileGroup = Entities.addGroup(TileEntity.class, false); diff --git a/core/src/io/anuke/mindustry/ai/BlockIndexer.java b/core/src/io/anuke/mindustry/ai/BlockIndexer.java index d82c6a8fe6..761140642e 100644 --- a/core/src/io/anuke/mindustry/ai/BlockIndexer.java +++ b/core/src/io/anuke/mindustry/ai/BlockIndexer.java @@ -203,7 +203,7 @@ public class BlockIndexer{ for(int x = Math.max(0, tile.x - oreQuadrantSize / 2); x < tile.x + oreQuadrantSize / 2 && x < world.width(); x++){ for(int y = Math.max(0, tile.y - oreQuadrantSize / 2); y < tile.y + oreQuadrantSize / 2 && y < world.height(); y++){ Tile res = world.tile(x, y); - if(res.block() == Blocks.air && res.floor().itemDrop == item){ + if(res.block() == Blocks.air && res.drop() == item){ return res; } } @@ -241,9 +241,9 @@ public class BlockIndexer{ for(int x = quadrantX * structQuadrantSize; x < world.width() && x < (quadrantX + 1) * structQuadrantSize; x++){ for(int y = quadrantY * structQuadrantSize; y < world.height() && y < (quadrantY + 1) * structQuadrantSize; y++){ Tile result = world.tile(x, y); - if( result == null || result.floor().itemDrop == null || !scanOres.contains(result.floor().itemDrop)) continue; + if( result == null || result.drop() == null || !scanOres.contains(result.drop())) continue; - itemSet.add(result.floor().itemDrop); + itemSet.add(result.drop()); } } @@ -280,7 +280,7 @@ public class BlockIndexer{ outer: for(int x = quadrantX * structQuadrantSize; x < world.width() && x < (quadrantX + 1) * structQuadrantSize; x++){ for(int y = quadrantY * structQuadrantSize; y < world.height() && y < (quadrantY + 1) * structQuadrantSize; y++){ - Tile result = world.tile(x, y); + Tile result = world.tile(x, y).target(); //when a targetable block is found, mark this quadrant as occupied and stop searching if(result.entity != null && result.getTeam() == data.team){ structQuadrants[data.team.ordinal()].set(index); @@ -320,8 +320,8 @@ public class BlockIndexer{ Tile tile = world.tile(x, y); //add position of quadrant to list when an ore is found - if(tile.floor().itemDrop != null && scanOres.contains(tile.floor().itemDrop) && tile.block() == Blocks.air){ - ores.get(tile.floor().itemDrop).add(world.tile( + if(tile.drop() != null && scanOres.contains(tile.drop()) && tile.block() == Blocks.air){ + ores.get(tile.drop()).add(world.tile( //make sure to clamp quadrant middle position, since it might go off bounds Mathf.clamp(qx * oreQuadrantSize + oreQuadrantSize / 2, 0, world.width() - 1), Mathf.clamp(qy * oreQuadrantSize + oreQuadrantSize / 2, 0, world.height() - 1))); diff --git a/core/src/io/anuke/mindustry/ai/Pathfinder.java b/core/src/io/anuke/mindustry/ai/Pathfinder.java index 9b5f4846b7..bd162140e5 100644 --- a/core/src/io/anuke/mindustry/ai/Pathfinder.java +++ b/core/src/io/anuke/mindustry/ai/Pathfinder.java @@ -146,6 +146,7 @@ public class Pathfinder{ while(path.frontier.size > 0 && (nsToRun < 0 || Time.timeSinceNanos(start) <= nsToRun)){ Tile tile = world.tile(path.frontier.removeLast()); + if(tile == null || path.weights == null) return; //something went horribly wrong, bail float cost = path.weights[tile.x][tile.y]; //pathfinding overflowed for some reason, time to bail. the next block update will handle this, hopefully diff --git a/core/src/io/anuke/mindustry/ai/WaveSpawner.java b/core/src/io/anuke/mindustry/ai/WaveSpawner.java index c32006b4de..cfdb2b134d 100644 --- a/core/src/io/anuke/mindustry/ai/WaveSpawner.java +++ b/core/src/io/anuke/mindustry/ai/WaveSpawner.java @@ -23,8 +23,7 @@ import java.io.IOException; import static io.anuke.mindustry.Vars.*; public class WaveSpawner{ - private static final float shockwaveBase = 380f, shockwaveRand = 50f, maxShockwaveDst = shockwaveBase + shockwaveRand; - private Array groups; + private static final float shockwaveBase = 380f, shockwaveRand = 0f, maxShockwaveDst = shockwaveBase + shockwaveRand; private Array flySpawns = new Array<>(); private Array groundSpawns = new Array<>(); private IntArray loadedSpawns = new IntArray(); @@ -59,7 +58,7 @@ public class WaveSpawner{ public void spawnEnemies(){ - for(SpawnGroup group : groups){ + for(SpawnGroup group : state.rules.spawns){ int spawned = group.getUnitsSpawned(state.wave); float spawnX, spawnY; @@ -105,7 +104,6 @@ public class WaveSpawner{ flySpawns.clear(); groundSpawns.clear(); - groups = state.rules.spawns; for(int x = 0; x < world.width(); x++){ for(int y = 0; y < world.height(); y++){ diff --git a/core/src/io/anuke/mindustry/content/Blocks.java b/core/src/io/anuke/mindustry/content/Blocks.java index 7b23fc2898..ab2ba4c56e 100644 --- a/core/src/io/anuke/mindustry/content/Blocks.java +++ b/core/src/io/anuke/mindustry/content/Blocks.java @@ -7,7 +7,6 @@ import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.mindustry.game.ContentList; import io.anuke.mindustry.graphics.CacheLayer; import io.anuke.mindustry.type.Category; -import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; @@ -27,18 +26,23 @@ import io.anuke.mindustry.world.blocks.units.RepairPoint; import io.anuke.mindustry.world.blocks.units.UnitFactory; import io.anuke.mindustry.world.consumers.ConsumeItemFilter; import io.anuke.mindustry.world.consumers.ConsumeLiquidFilter; +import io.anuke.mindustry.world.meta.Attribute; -import static io.anuke.mindustry.Vars.*; +import static io.anuke.mindustry.Vars.state; +import static io.anuke.mindustry.Vars.world; public class Blocks implements ContentList{ public static Block //environment air, part, spawn, deepwater, water, tar, stone, craters, charr, sand, ice, snow, - holostone, rocks, icerocks, cliffs, pine, whiteTree, whiteTreeDead, sporeCluster, - iceSnow, sandWater, duneRocks, stainedRocks, stainedStone, stainedRocksRed, stainedStoneRed, stainedRocksYellow, stainedStoneYellow, stainedBoulder, + holostone, rocks, icerocks, cliffs, sporePine, pine, whiteTree, whiteTreeDead, sporeCluster, + iceSnow, sandWater, duneRocks, sandRocks, moss, sporeMoss, shale, shaleRocks, shaleBoulder, grass, salt, metalFloor, metalFloorDamaged, metalFloor2, metalFloor3, metalFloor5, ignarock, magmarock, hotrock, snowrocks, + //ores + oreCopper, oreLead, oreScrap, oreCoal, oreTitanium, oreThorium, + //crafting siliconSmelter, kiln, graphitePress, plastaniumCompressor, multiPress, phaseWeaver, surgeSmelter, pyratiteMixer, blastMixer, cryofluidMixer, melter, separator, sporePress, pulverizer, incinerator, @@ -68,10 +72,10 @@ public class Blocks implements ContentList{ coreShard, coreFoundation, coreNucleus, vault, container, unloader, launchPad, //turrets - duo, hail, arc, wave, lancer, swarmer, salvo, fuse, ripple, cyclone, spectre, meltdown, + duo, scatter, hail, arc, wave, lancer, swarmer, salvo, fuse, ripple, cyclone, spectre, meltdown, //units - spiritFactory, phantomFactory, wraithFactory, ghoulFactory, revenantFactory, daggerFactory, titanFactory, + spiritFactory, phantomFactory, wraithFactory, ghoulFactory, revenantFactory, daggerFactory, crawlerFactory, titanFactory, fortressFactory, repairPoint, //upgrades @@ -141,11 +145,11 @@ public class Blocks implements ContentList{ variants = 0; liquidDrop = Liquids.oil; isLiquid = true; - cacheLayer = CacheLayer.oil; + cacheLayer = CacheLayer.tar; }}; stone = new Floor("stone"){{ - hasOres = true; + }}; craters = new Floor("craters"){{ @@ -170,26 +174,35 @@ public class Blocks implements ContentList{ sand = new Floor("sand"){{ itemDrop = Items.sand; - hasOres = true; playerUnmineable = true; }}; holostone = new Floor("holostone"){{ - hasOres = true; edgeStyle = "blocky"; }}; + grass = new Floor("grass"){{ + + }}; + + salt = new Floor("salt"){{ + variants = 0; + }}; + iceSnow = new Floor("ice-snow"){{ variants = 3; + attributes.set(Attribute.water, 0.3f); }}; snow = new Floor("snow"){{ + attributes.set(Attribute.water, 0.2f); }}; ice = new Floor("ice"){{ - //TODO fix + //TODO fix drag/speed dragMultiplier = 1f; speedMultiplier = 1f; + attributes.set(Attribute.water, 0.4f); }}; cliffs = new StaticWall("cliffs"){{ @@ -213,8 +226,15 @@ public class Blocks implements ContentList{ variants = 2; }}; + sandRocks = new StaticWall("sandrocks"){{ + variants = 2; + }}; + + sporePine = new StaticWall("spore-pine"){{ + variants = 0; + }}; + pine = new StaticWall("pine"){{ - //fillsTile = false; variants = 0; }}; @@ -228,34 +248,27 @@ public class Blocks implements ContentList{ variants = 3; }}; - stainedRocks = new StaticWall("stained-rocks"){{ + shale = new Floor("shale"){{ + variants = 3; + attributes.set(Attribute.oil, 0.15f); + }}; + + shaleRocks = new StaticWall("shalerocks"){{ variants = 2; }}; - stainedStone = new Floor("stained-stone"){{ - edgeStyle = "blocky"; - hasOres = true; - }}; - - stainedRocksRed = new StaticWall("stained-rocks-red"){{ + shaleBoulder = new Rock("shale-boulder"){{ variants = 2; }}; - stainedStoneRed = new Floor("stained-stone-red"){{ - edgeStyle = "blocky"; - hasOres = true; + moss = new Floor("moss"){{ + variants = 3; + attributes.set(Attribute.spores, 0.15f); }}; - stainedRocksYellow = new StaticWall("stained-rocks-yellow"){{ - variants = 2; - }}; - - stainedStoneYellow = new Floor("stained-stone-yellow"){{ - edgeStyle = "blocky"; - }}; - - stainedBoulder = new Rock("stained-boulder"){{ - variants = 2; + sporeMoss = new Floor("spore-moss"){{ + variants = 3; + attributes.set(Attribute.spores, 0.3f); }}; metalFloor = new Floor("metal-floor"){{ @@ -264,39 +277,45 @@ public class Blocks implements ContentList{ metalFloorDamaged = new Floor("metal-floor-damaged"){{ variants = 6; - blendGroup = metalFloor; }}; metalFloor2 = new Floor("metal-floor-2"){{ variants = 0; - blendGroup = metalFloor; }}; metalFloor3 = new Floor("metal-floor-3"){{ variants = 0; - blendGroup = metalFloor; }}; metalFloor5 = new Floor("metal-floor-5"){{ variants = 0; - blendGroup = metalFloor; }}; ignarock = new Floor("ignarock"){{ - blendGroup = sand; + }}; hotrock = new Floor("hotrock"){{ - heat = 0.5f; - blendGroup = sand; + attributes.set(Attribute.heat, 0.5f); + blendGroup = ignarock; }}; magmarock = new Floor("magmarock"){{ - heat = 0.75f; + attributes.set(Attribute.heat, 0.75f); updateEffect = Fx.magmasmoke; - blendGroup = sand; + blendGroup = ignarock; }}; + //endregion + //region ore + + oreCopper = new OreBlock(Items.copper); + oreLead = new OreBlock(Items.lead); + oreScrap = new OreBlock(Items.scrap); + oreCoal = new OreBlock(Items.coal); + oreTitanium = new OreBlock(Items.titanium); + oreThorium = new OreBlock(Items.thorium); + //endregion //region crafting @@ -717,7 +736,8 @@ public class Blocks implements ContentList{ massDriver = new MassDriver("mass-driver"){{ requirements(Category.distribution, ItemStack.with(Items.titanium, 250, Items.silicon, 150, Items.lead, 250, Items.thorium, 100)); size = 3; - itemCapacity = 60; + itemCapacity = 120; + reloadTime = 200f; range = 440f; }}; @@ -732,7 +752,7 @@ public class Blocks implements ContentList{ rotaryPump = new Pump("rotary-pump"){{ requirements(Category.liquid, ItemStack.with(Items.copper, 140, Items.lead, 100, Items.silicon, 40, Items.titanium, 70)); pumpAmount = 0.8f; - consumes.power(1.50f); + consumes.power(0.15f); liquidCapacity = 30f; hasPower = true; size = 2; @@ -950,6 +970,7 @@ public class Blocks implements ContentList{ size = 2; liquidCapacity = 30f; rotateSpeed = 1.4f; + attribute = Attribute.water; consumes.power(0.90f); }}; @@ -963,6 +984,7 @@ public class Blocks implements ContentList{ pumpAmount = 0.25f; size = 3; liquidCapacity = 30f; + attribute = Attribute.oil; consumes.item(Items.sand); consumes.power(3f); @@ -977,7 +999,7 @@ public class Blocks implements ContentList{ alwaysUnlocked = true; health = 1100; - itemCapacity = 3000; + itemCapacity = 5000; size = 3; }}; @@ -985,7 +1007,7 @@ public class Blocks implements ContentList{ requirements(Category.effect, () -> false, ItemStack.with(Items.titanium, 3000, Items.silicon, 2000)); health = 2000; - itemCapacity = 6000; + itemCapacity = 9000; size = 4; }}; @@ -993,7 +1015,7 @@ public class Blocks implements ContentList{ requirements(Category.effect, () -> false, ItemStack.with(Items.titanium, 8000, Items.silicon, 4000, Items.surgealloy, 2000)); health = 4000; - itemCapacity = 10000; + itemCapacity = 13000; size = 5; }}; @@ -1044,6 +1066,26 @@ public class Blocks implements ContentList{ rotatespeed = 10f; }}; + scatter = new BurstTurret("scatter"){{ + requirements(Category.turret, ItemStack.with(Items.copper, 170, Items.lead, 90), true); + ammo( + Items.scrap, Bullets.flakScrap, + Items.lead, Bullets.flakLead + ); + reload = 45f; + range = 160f; + size = 2; + burstSpacing = 5f; + shots = 2; + + recoil = 2f; + rotatespeed = 10f; + inaccuracy = 18f; + shootCone = 35f; + + health = 220*size*size; + }}; + hail = new ArtilleryTurret("hail"){{ requirements(Category.turret, ItemStack.with(Items.copper, 60, Items.graphite, 35)); ammo( @@ -1116,6 +1158,7 @@ public class Blocks implements ContentList{ shootCone = 40f; rotatespeed = 8f; powerUsed = 1f / 2f; + targetAir = false; consumes.powerBuffered(80f); range = 80f; shootEffect = Fx.lightningShoot; @@ -1199,7 +1242,7 @@ public class Blocks implements ContentList{ ); xRand = 4f; reload = 8f; - range = 145f; + range = 160f; size = 3; recoil = 3f; rotatespeed = 10f; @@ -1258,7 +1301,7 @@ public class Blocks implements ContentList{ powerUsed = 0.5f; consumes.powerBuffered(1200f); range = 160f; - reload = 200f; + reload = 170f; firingMoveFract = 0.1f; shootDuration = 220f; @@ -1322,6 +1365,15 @@ public class Blocks implements ContentList{ consumes.items(new ItemStack(Items.silicon, 10)); }}; + crawlerFactory = new UnitFactory("crawler-factory"){{ + requirements(Category.units, ItemStack.with(Items.lead, 100, Items.silicon, 80)); + type = UnitTypes.crawler; + produceTime = 1200; + size = 2; + consumes.power(0.4f); + consumes.items(new ItemStack(Items.blastCompound, 10)); + }}; + titanFactory = new UnitFactory("titan-factory"){{ requirements(Category.units, ItemStack.with(Items.thorium, 90, Items.lead, 140, Items.silicon, 90)); type = UnitTypes.titan; @@ -1397,23 +1449,6 @@ public class Blocks implements ContentList{ consumes.powerBuffered(120f); }}; - //endregion - //region ores - - //create ores for every floor and item combination necessary - for(Item item : content.items()){ - if(!item.genOre) continue; - - for(Block block : content.blocks()){ - if(block instanceof Floor && ((Floor) block).hasOres){ - new OreBlock(item, (Floor) block); - } - } - } - - //special variants - new OreBlock(Items.scrap, (Floor)snow); - //endregion } } diff --git a/core/src/io/anuke/mindustry/content/Bullets.java b/core/src/io/anuke/mindustry/content/Bullets.java index e0f4ed0a96..1dec6813d2 100644 --- a/core/src/io/anuke/mindustry/content/Bullets.java +++ b/core/src/io/anuke/mindustry/content/Bullets.java @@ -30,7 +30,7 @@ public class Bullets implements ContentList{ artilleryDense, arilleryPlastic, artilleryPlasticFrag, artilleryHoming, artlleryIncendiary, artilleryExplosive, artilleryUnit, //flak - flakPlastic, flakExplosive, flakSurge, + flakScrap, flakLead, flakPlastic, flakExplosive, flakSurge, //missiles missileExplosive, missileIncendiary, missileSurge, missileJavelin, missileSwarm, missileRevenant, @@ -140,6 +140,25 @@ public class Bullets implements ContentList{ frontColor = Pal.bulletYellow; }}; + flakLead = new FlakBulletType(3.9f, 3){{ + shootEffect = Fx.shootSmall; + bulletWidth = 6f; + bulletHeight = 8f; + hitEffect = Fx.flakExplosion; + splashDamage = 25f; + splashDamageRadius = 15f; + }}; + + flakScrap = new FlakBulletType(3.5f, 3){{ + shootEffect = Fx.shootSmall; + reloadMultiplier = 0.5f; + bulletWidth = 6f; + bulletHeight = 8f; + hitEffect = Fx.flakExplosion; + splashDamage = 16f; + splashDamageRadius = 24f; + }}; + flakPlastic = new FlakBulletType(4f, 6){{ splashDamageRadius = 50f; fragBullet = artilleryPlasticFrag; @@ -360,6 +379,7 @@ public class Bullets implements ContentList{ { shootEffect = Fx.shootHeal; + smokeEffect = Fx.hitLaser; hitEffect = Fx.hitLaser; despawnEffect = Fx.hitLaser; collidesTeam = true; @@ -609,6 +629,11 @@ public class Bullets implements ContentList{ keepVelocity = false; } + @Override + public float range(){ + return 70f; + } + @Override public void draw(Bullet b){ } @@ -684,29 +709,17 @@ public class Bullets implements ContentList{ hitEffect = Fx.pulverize; lifetime = 23f; speed = 1f; - splashDamageRadius = 60f; - splashDamage = 30f; + splashDamageRadius = 50f; + splashDamage = 20f; } @Override public void init(Bullet b){ if(b.getOwner() instanceof Unit){ - Unit unit = (Unit)b.getOwner(); - - unit.damage(unit.maxHealth() + 1); + ((Unit)b.getOwner()).kill(); } b.time(b.lifetime()); } - - @Override - public void hit(Bullet b, float x, float y){ - super.hit(b, x, y); - - for(int i = 0; i < 3; i++){ - Tile tile = world.tileWorld(x + Mathf.range(8f), y + Mathf.range(8f)); - Puddle.deposit(tile, Liquids.oil, 5f); - } - } }; } } diff --git a/core/src/io/anuke/mindustry/content/Fx.java b/core/src/io/anuke/mindustry/content/Fx.java index dece137ea4..d99024d745 100644 --- a/core/src/io/anuke/mindustry/content/Fx.java +++ b/core/src/io/anuke/mindustry/content/Fx.java @@ -162,7 +162,7 @@ public class Fx implements ContentList{ heal = new Effect(11, e -> { Draw.color(Pal.heal); Lines.stroke(e.fout() * 2f); - Lines.poly(e.x, e.y, 10, 2f + e.finpow() * 7f); + Lines.poly(e.x, e.y, 24, 2f + e.finpow() * 7f); Draw.color(); }); diff --git a/core/src/io/anuke/mindustry/content/Items.java b/core/src/io/anuke/mindustry/content/Items.java index 6c1fcdfa80..ad5f0ba779 100644 --- a/core/src/io/anuke/mindustry/content/Items.java +++ b/core/src/io/anuke/mindustry/content/Items.java @@ -15,7 +15,6 @@ public class Items implements ContentList{ type = ItemType.material; hardness = 1; cost = 0.6f; - genOre = true; alwaysUnlocked = true; }}; @@ -23,7 +22,6 @@ public class Items implements ContentList{ type = ItemType.material; hardness = 1; cost = 0.9f; - genOre = true; }}; metaglass = new Item("metaglass", Color.valueOf("ebeef5")){{ @@ -40,14 +38,12 @@ public class Items implements ContentList{ explosiveness = 0.4f; flammability = 1f; hardness = 2; - genOre = true; }}; titanium = new Item("titanium", Color.valueOf("8da1e3")){{ type = ItemType.material; hardness = 3; cost = 1.1f; - genOre = true; }}; thorium = new Item("thorium", Color.valueOf("f9a3c7")){{ @@ -56,11 +52,10 @@ public class Items implements ContentList{ hardness = 4; radioactivity = 1f; cost = 1.4f; - genOre = true; }}; scrap = new Item("scrap", Color.valueOf("777777")){{ - genOre = true; + }}; silicon = new Item("silicon", Color.valueOf("53565c")){{ @@ -89,7 +84,7 @@ public class Items implements ContentList{ flammability = 1.05f; }}; - sand = new Item("sand", Color.valueOf("e3d39e")){{ + sand = new Item("sand", Color.valueOf("f7cba4")){{ }}; diff --git a/core/src/io/anuke/mindustry/content/TechTree.java b/core/src/io/anuke/mindustry/content/TechTree.java index 0ac28a96a9..46e34eb01d 100644 --- a/core/src/io/anuke/mindustry/content/TechTree.java +++ b/core/src/io/anuke/mindustry/content/TechTree.java @@ -15,9 +15,6 @@ public class TechTree implements ContentList{ root = node(coreShard, () -> { node(conveyor, () -> { - node(launchPad, () -> { - - }); node(junction, () -> { node(itemBridge); @@ -28,7 +25,9 @@ public class TechTree implements ContentList{ node(container, () -> { node(unloader); node(vault, () -> { + node(launchPad, () -> { + }); }); }); @@ -100,25 +99,25 @@ public class TechTree implements ContentList{ }); node(mechanicalDrill, () -> { - node(pneumaticDrill, () -> { - node(cultivator, () -> { - - }); - - node(laserDrill, () -> { - node(blastDrill, () -> { + node(graphitePress, () -> { + node(pneumaticDrill, () -> { + node(cultivator, () -> { }); - node(waterExtractor, () -> { - node(oilExtractor, () -> { + node(laserDrill, () -> { + node(blastDrill, () -> { }); + + node(waterExtractor, () -> { + node(oilExtractor, () -> { + + }); + }); }); }); - }); - node(graphitePress, () -> { node(pyratiteMixer, () -> { node(blastMixer, () -> { @@ -185,68 +184,68 @@ public class TechTree implements ContentList{ }); }); }); - }); - node(powerNode, () -> { node(combustionGenerator, () -> { - node(powerNodeLarge, () -> { - node(battery, () -> { - node(batteryLarge, () -> { - node(surgeTower, () -> { + node(powerNode, () -> { + node(powerNodeLarge, () -> { + node(battery, () -> { + node(batteryLarge, () -> { + node(surgeTower, () -> { + + }); + }); + }); + + node(mendProjector, () -> { + node(forceProjector, () -> { + node(overdriveProjector, () -> { + + }); + }); + + node(repairPoint, () -> { }); }); }); - node(mendProjector, () -> { - node(forceProjector, () -> { - node(overdriveProjector, () -> { - - }); - }); - - node(repairPoint, () -> { - - }); - }); - }); - - node(turbineGenerator, () -> { - node(thermalGenerator, () -> { - node(rtgGenerator, () -> { - node(differentialGenerator, () -> { - node(thoriumReactor, () -> { - node(impactReactor, () -> { + node(turbineGenerator, () -> { + node(thermalGenerator, () -> { + node(rtgGenerator, () -> { + node(differentialGenerator, () -> { + node(thoriumReactor, () -> { + node(impactReactor, () -> { + }); }); }); }); }); }); - }); - node(solarPanel, () -> { - node(largeSolarPanel, () -> { + node(solarPanel, () -> { + node(largeSolarPanel, () -> { - }); - }); - }); - - node(alphaDartPad, () -> { - node(deltaPad, () -> { - node(spiritFactory, () -> { - node(phantomFactory); - }); - - node(javelinPad, () -> { - node(tridentPad, () -> { - node(glaivePad); }); }); + }); - node(tauPad, () -> { - node(omegaPad, () -> { + node(alphaDartPad, () -> { + node(deltaPad, () -> { + node(spiritFactory, () -> { + node(phantomFactory); + }); + node(javelinPad, () -> { + node(tridentPad, () -> { + node(glaivePad); + }); + }); + + node(tauPad, () -> { + node(omegaPad, () -> { + + }); }); }); }); @@ -258,7 +257,7 @@ public class TechTree implements ContentList{ private TechNode node(Block block, Runnable children){ ItemStack[] requirements = new ItemStack[block.buildRequirements.length]; for(int i = 0; i < requirements.length; i++){ - requirements[i] = new ItemStack(block.buildRequirements[i].item, block.buildRequirements[i].amount * 30); + requirements[i] = new ItemStack(block.buildRequirements[i].item, block.buildRequirements[i].amount * 10); } return new TechNode(block, requirements, children); diff --git a/core/src/io/anuke/mindustry/content/Zones.java b/core/src/io/anuke/mindustry/content/Zones.java index d2bd4d6b73..9d94ce230e 100644 --- a/core/src/io/anuke/mindustry/content/Zones.java +++ b/core/src/io/anuke/mindustry/content/Zones.java @@ -1,9 +1,7 @@ package io.anuke.mindustry.content; -import io.anuke.arc.collection.Array; import io.anuke.mindustry.game.ContentList; import io.anuke.mindustry.game.Rules; -import io.anuke.mindustry.game.SpawnGroup; import io.anuke.mindustry.maps.generators.MapGenerator; import io.anuke.mindustry.maps.generators.MapGenerator.Decoration; import io.anuke.mindustry.type.Item; @@ -12,15 +10,15 @@ import io.anuke.mindustry.type.Zone; import io.anuke.mindustry.world.Block; public class Zones implements ContentList{ - public static Zone groundZero, craters, frozenForest, ruinousShores, crags, stainedMountains, - impact, desolateRift, arcticDesert, dryWastes, nuclearComplex, moltenFault; + public static Zone groundZero, craters, frozenForest, ruinousShores, stainedMountains, + desolateRift, nuclearComplex; @Override public void load(){ groundZero = new Zone("groundZero", new MapGenerator("groundZero", 1)){{ - baseLaunchCost = ItemStack.with(Items.copper, -50); - startingItems = ItemStack.list(Items.copper, 50); + baseLaunchCost = ItemStack.with(Items.copper, -100); + startingItems = ItemStack.list(Items.copper, 100); alwaysUnlocked = true; conditionWave = 5; launchPeriod = 5; @@ -29,39 +27,6 @@ public class Zones implements ContentList{ waves = true; waveTimer = true; waveSpacing = 60 * 60 * 2; - spawns = Array.with( - new SpawnGroup(UnitTypes.dagger){{ - unitScaling = 1.5f; - }}, - - new SpawnGroup(UnitTypes.dagger){{ - begin = 5; - unitScaling = 2; - }}, - - new SpawnGroup(UnitTypes.dagger){{ - begin = 15; - unitScaling = 3; - }}, - - new SpawnGroup(UnitTypes.dagger){{ - begin = 20; - unitScaling = 3; - }}, - - new SpawnGroup(UnitTypes.dagger){{ - begin = 25; - unitScaling = 3; - }}, - - new SpawnGroup(UnitTypes.dagger){{ - begin = 30; - unitScaling = 2; - }}, - - - bossGroup(UnitTypes.fortress) - ); }}; }}; @@ -76,49 +41,13 @@ public class Zones implements ContentList{ waves = true; waveTimer = true; waveSpacing = 60 * 60 * 1f; - spawns = Array.with( - new SpawnGroup(UnitTypes.crawler){{ - unitScaling = 1.5f; - }}, - - new SpawnGroup(UnitTypes.crawler){{ - begin = 5; - unitAmount = 2; - spacing = 2; - unitScaling = 2; - }}, - - new SpawnGroup(UnitTypes.dagger){{ - begin = 3; - unitScaling = 1.5f; - }}, - - new SpawnGroup(UnitTypes.crawler){{ - begin = 15; - unitScaling = 1; - unitAmount = 2; - }}, - - new SpawnGroup(UnitTypes.dagger){{ - begin = 20; - unitScaling = 2; - }}, - - new SpawnGroup(UnitTypes.crawler){{ - begin = 25; - unitScaling = 1; - unitAmount = 2; - }}, - - bossGroup(UnitTypes.revenant) - ); }}; }}; frozenForest = new Zone("frozenForest", new MapGenerator("frozenForest", 1) .decor(new Decoration(Blocks.snow, Blocks.sporeCluster, 0.02))){{ loadout = Loadouts.basicFoundation; - baseLaunchCost = ItemStack.with(Items.copper, 100); + baseLaunchCost = ItemStack.with(); startingItems = ItemStack.list(Items.copper, 400); conditionWave = 10; zoneRequirements = new Zone[]{craters}; @@ -128,67 +57,12 @@ public class Zones implements ContentList{ waves = true; waveTimer = true; waveSpacing = 60 * 60 * 1.5f; - spawns = Array.with( - new SpawnGroup(UnitTypes.titan){{ - unitScaling = 3; - end = 9; - }}, - - new SpawnGroup(UnitTypes.dagger){{ - unitScaling = 2; - begin = 2; - end = 9; - }}, - - new SpawnGroup(UnitTypes.dagger){{ - unitScaling = 2; - begin = 5; - end = 9; - }}, - - new SpawnGroup(UnitTypes.crawler){{ - unitScaling = 0.5f; - begin = 10; - spacing = 10; - unitAmount = 5; - }}, - - new SpawnGroup(UnitTypes.titan){{ - begin = 11; - unitAmount = 2; - unitScaling = 2; - spacing = 2; - }}, - - new SpawnGroup(UnitTypes.dagger){{ - begin = 12; - unitAmount = 2; - unitScaling = 2; - spacing = 2; - }}, - - new SpawnGroup(UnitTypes.crawler){{ - unitScaling = 0.5f; - begin = 35; - spacing = 10; - unitAmount = 6; - }}, - - //boss - new SpawnGroup(UnitTypes.revenant){{ - begin = configureWave; - effect = StatusEffects.boss; - unitScaling = never; - }}, - - bossGroup(UnitTypes.eruptor) - ); }}; }}; - ruinousShores = new Zone("ruinousShores", new MapGenerator("ruinousShores", 1)){{ + ruinousShores = new Zone("ruinousShores", new MapGenerator("ruinousShores", 1).dist(3f, true)){{ loadout = Loadouts.basicFoundation; - baseLaunchCost = ItemStack.with(Items.copper, 200, Items.graphite, 50); + baseLaunchCost = ItemStack.with(); startingItems = ItemStack.list(Items.copper, 400); conditionWave = 20; launchPeriod = 20; @@ -199,67 +73,7 @@ public class Zones implements ContentList{ rules = () -> new Rules(){{ waves = true; waveTimer = true; - waveSpacing = 60 * 60; - spawns = Array.with( - new SpawnGroup(UnitTypes.wraith){{ - unitScaling = 2; - spacing = 2; - end = 10; - }}, - - new SpawnGroup(UnitTypes.dagger){{ - begin = 1; - spacing = 2; - unitScaling = 2; - }}, - - new SpawnGroup(UnitTypes.wraith){{ - begin = 10; - unitScaling = 0.5f; - unitAmount = 6; - spacing = 10; - }}, - - new SpawnGroup(UnitTypes.crawler){{ - begin = 5; - unitScaling = 1; - spacing = 5; - unitAmount = 1; - effect = StatusEffects.overdrive; - }}, - - new SpawnGroup(UnitTypes.crawler){{ - begin = 22; - unitScaling = 1; - spacing = 20; - unitScaling = 0.5f; - unitAmount = 10; - }}, - - new SpawnGroup(UnitTypes.dagger){{ - begin = 11; - spacing = 2; - unitScaling = 2; - unitAmount = 2; - }}, - - new SpawnGroup(UnitTypes.dagger){{ - begin = 12; - spacing = 2; - unitScaling = 2; - unitAmount = 2; - }}, - - new SpawnGroup(UnitTypes.crawler){{ - begin = 12; - spacing = 3; - unitScaling = 3; - unitAmount = 2; - }}, - - bossGroup(UnitTypes.revenant), - bossGroup(UnitTypes.revenant) - ); + waveSpacing = 60 * 80; }}; }}; @@ -279,9 +93,9 @@ public class Zones implements ContentList{ stainedMountains = new Zone("stainedMountains", new MapGenerator("stainedMountains", 2) .dist(2.5f, true) - .decor(new Decoration(Blocks.stainedStone, Blocks.stainedBoulder, 0.01))){{ + .decor(new Decoration(Blocks.moss, Blocks.shaleBoulder, 0.02))){{ loadout = Loadouts.basicFoundation; - baseLaunchCost = ItemStack.with(Items.copper, 100, Items.lead, 200, Items.silicon, 100); + baseLaunchCost = ItemStack.with(); startingItems = ItemStack.list(Items.copper, 400, Items.lead, 100); conditionWave = 10; launchPeriod = 10; @@ -293,154 +107,12 @@ public class Zones implements ContentList{ waves = true; waveTimer = true; waveSpacing = 60 * 60 * 2; - spawns = Array.with( - new SpawnGroup(UnitTypes.titan){{ - unitScaling = 2; - spacing = 2; - end = 10; - }}, - - new SpawnGroup(UnitTypes.dagger){{ - begin = 1; - unitScaling = 1; - spacing = 2; - }}, - - new SpawnGroup(UnitTypes.dagger){{ - begin = 11; - spacing = 2; - unitScaling = 2; - unitAmount = 2; - }}, - - new SpawnGroup(UnitTypes.ghoul){{ - begin = 6; - unitScaling = 0.5f; - unitAmount = 1; - spacing = 5; - }}, - - new SpawnGroup(UnitTypes.wraith){{ - begin = 10; - unitScaling = 1f; - unitAmount = 1; - spacing = 5; - }}, - - new SpawnGroup(UnitTypes.dagger){{ - begin = 2; - unitScaling = 1; - spacing = 2; - }}, - - new SpawnGroup(UnitTypes.wraith){{ - begin = 23; - unitScaling = 1f; - unitAmount = 1; - spacing = 2; - }}, - - new SpawnGroup(UnitTypes.crawler){{ - begin = 20; - unitScaling = 1; - spacing = 10; - unitScaling = 0.5f; - unitAmount = 10; - }}, - - bossGroup(UnitTypes.chaosArray) - ); - }}; - }}; - - impact = new Zone("impact0079", new MapGenerator("impact0079", 2) - .dist(2.2f, true) - .decor( - new Decoration(Blocks.snow, Blocks.sporeCluster, 0.01), - new Decoration(Blocks.metalFloor, Blocks.metalFloorDamaged, 0.02) - ).drops(ItemStack.with(Items.copper, 2000, Items.lead, 1500, Items.silicon, 1000, Items.graphite, 2000, Items.pyratite, 2000, Items.titanium, 2000, Items.metaglass, 1000, Items.coal, 2000))){{ - loadout = Loadouts.basicFoundation; - baseLaunchCost = ItemStack.with(Items.copper, 500, Items.lead, 500, Items.silicon, 100); - startingItems = ItemStack.list(Items.copper, 2000, Items.lead, 500, Items.silicon, 200, Items.titanium, 400, Items.graphite, 200); - itemRequirements = ItemStack.with(Items.silicon, 8000, Items.titanium, 6000, Items.graphite, 4000); - conditionWave = 20; - zoneRequirements = new Zone[]{stainedMountains}; - blockRequirements = new Block[]{Blocks.launchPad, Blocks.unloader, Blocks.melter, Blocks.separator}; - resources = new Item[]{Items.scrap}; - rules = () -> new Rules(){{ - waves = true; - waveTimer = true; - waveSpacing = 60 * 60; - - spawns = Array.with( - new SpawnGroup(UnitTypes.titan){{ - unitScaling = 2; - spacing = 2; - end = 10; - }}, - - new SpawnGroup(UnitTypes.dagger){{ - begin = 1; - unitScaling = 1; - spacing = 2; - }}, - - new SpawnGroup(UnitTypes.dagger){{ - begin = 2; - unitScaling = 1; - spacing = 2; - }}, - - new SpawnGroup(UnitTypes.dagger){{ - begin = 10; - spacing = 2; - unitScaling = 2; - unitAmount = 2; - }}, - - new SpawnGroup(UnitTypes.ghoul){{ - begin = 5; - unitScaling = 0.5f; - unitAmount = 1; - spacing = 5; - }}, - - new SpawnGroup(UnitTypes.wraith){{ - begin = 10; - unitScaling = 1f; - unitAmount = 1; - spacing = 5; - }}, - - new SpawnGroup(UnitTypes.dagger){{ - begin = 2; - unitScaling = 1; - spacing = 2; - }}, - - new SpawnGroup(UnitTypes.wraith){{ - begin = 23; - unitScaling = 1f; - unitAmount = 1; - spacing = 2; - }}, - - new SpawnGroup(UnitTypes.crawler){{ - begin = 20; - unitScaling = 1; - spacing = 10; - unitScaling = 0.5f; - unitAmount = 10; - }}, - - bossGroup(UnitTypes.lich) - ); }}; }}; desolateRift = new Zone("desolateRift", new MapGenerator("desolateRift").dist(2f)){{ loadout = Loadouts.basicNucleus; - baseLaunchCost = ItemStack.with(Items.copper, 500); + baseLaunchCost = ItemStack.with(); startingItems = ItemStack.list(Items.copper, 1500); itemRequirements = ItemStack.with(Items.copper, 8000, Items.metaglass, 2000, Items.graphite, 3000); conditionWave = 10; @@ -452,195 +124,26 @@ public class Zones implements ContentList{ waves = true; waveTimer = true; waveSpacing = 60 * 60 * 1.5f; - spawns = Array.with( - new SpawnGroup(UnitTypes.crawler){{ - unitScaling = 1; - spacing = 2; - end = 10; - }}, - - new SpawnGroup(UnitTypes.titan){{ - begin = 1; - unitScaling = 3; - spacing = 2; - }}, - - new SpawnGroup(UnitTypes.dagger){{ - begin = 2; - spacing = 2; - unitScaling = 2; - }}, - - new SpawnGroup(UnitTypes.titan){{ - begin = 10; - unitScaling = 1f; - unitAmount = 3; - spacing = 3; - }}, - - new SpawnGroup(UnitTypes.fortress){{ - begin = 5; - unitScaling = 1; - spacing = 5; - unitAmount = 1; - }}, - - new SpawnGroup(UnitTypes.fortress){{ - begin = 13; - unitScaling = 1; - spacing = 4; - unitAmount = 1; - }}, - - new SpawnGroup(UnitTypes.dagger){{ - begin = 11; - spacing = 2; - unitScaling = 2; - unitAmount = 2; - }}, - - new SpawnGroup(UnitTypes.crawler){{ - unitScaling = 1; - spacing = 2; - unitAmount = 4; - begin = 13; - }}, - - bossGroup(UnitTypes.chaosArray) - ); }}; }}; - /* - arcticDesert = new Zone("arcticDesert", new MapGenerator("groundZero", 1)){{ //TODO implement - baseLaunchCost = ItemStack.with(Items.copper, 300); - startingItems = ItemStack.with(Items.copper, 200); - conditionWave = 15; - zoneRequirements = new Zone[]{frozenForest}; - blockRequirements = new Block[]{Blocks.copperWall}; - rules = () -> new Rules(){{ - waves = true; - waveTimer = true; - waveSpacing = 60 * 80; - }}; - }}; - - dryWastes = new Zone("dryWastes", new MapGenerator("groundZero", 1)){{ //TODO implement - baseLaunchCost = ItemStack.with(Items.copper, 300); - startingItems = ItemStack.with(Items.copper, 200); - conditionWave = 15; - zoneRequirements = new Zone[]{frozenForest}; - blockRequirements = new Block[]{Blocks.copperWall}; - rules = () -> new Rules(){{ - waves = true; - waveTimer = true; - waveSpacing = 60 * 80; - }}; - }}; - - */ nuclearComplex = new Zone("nuclearComplex", new MapGenerator("nuclearProductionComplex", 1) .drops(ItemStack.with(Items.copper, 2000, Items.lead, 1500, Items.silicon, 1000, Items.graphite, 1000, Items.thorium, 200, Items.titanium, 2000, Items.metaglass, 1000)) .decor(new Decoration(Blocks.snow, Blocks.sporeCluster, 0.01))){{ loadout = Loadouts.basicNucleus; - baseLaunchCost = ItemStack.with(Items.copper, 500, Items.silicon, 200, Items.metaglass, 100); + baseLaunchCost = ItemStack.with(); startingItems = ItemStack.list(Items.copper, 2500, Items.lead, 3000, Items.silicon, 800, Items.metaglass, 400); itemRequirements = ItemStack.with(Items.copper, 10000, Items.titanium, 8000, Items.metaglass, 6000, Items.plastanium, 2000); conditionWave = 30; launchPeriod = 15; - zoneRequirements = new Zone[]{impact}; + zoneRequirements = new Zone[]{desolateRift}; blockRequirements = new Block[]{Blocks.blastDrill, Blocks.thermalGenerator}; resources = new Item[]{Items.copper, Items.scrap, Items.lead, Items.coal, Items.titanium, Items.thorium, Items.sand}; rules = () -> new Rules(){{ waves = true; waveTimer = true; waveSpacing = 60 * 60 * 2; - - spawns = Array.with( - new SpawnGroup(UnitTypes.titan){{ - unitScaling = 2; - spacing = 2; - end = 10; - }}, - - new SpawnGroup(UnitTypes.crawler){{ - begin = 1; - unitScaling = 2; - spacing = 2; - unitAmount = 3; - }}, - - new SpawnGroup(UnitTypes.dagger){{ - begin = 2; - unitScaling = 1; - spacing = 2; - }}, - - new SpawnGroup(UnitTypes.dagger){{ - begin = 10; - spacing = 2; - unitScaling = 2; - unitAmount = 2; - }}, - - new SpawnGroup(UnitTypes.ghoul){{ - begin = 5; - unitScaling = 0.5f; - unitAmount = 1; - spacing = 5; - }}, - - new SpawnGroup(UnitTypes.fortress){{ - begin = 13; - unitScaling = 2; - spacing = 3; - }}, - - new SpawnGroup(UnitTypes.wraith){{ - begin = 10; - unitScaling = 1f; - unitAmount = 1; - spacing = 5; - }}, - - new SpawnGroup(UnitTypes.dagger){{ - begin = 2; - unitScaling = 1; - spacing = 2; - }}, - - new SpawnGroup(UnitTypes.wraith){{ - begin = 23; - unitScaling = 1f; - unitAmount = 1; - spacing = 2; - }}, - - new SpawnGroup(UnitTypes.crawler){{ - begin = 20; - unitScaling = 1; - spacing = 10; - unitScaling = 0.5f; - unitAmount = 10; - }}, - - bossGroup(UnitTypes.reaper) - ); }}; }}; - - /* - moltenFault = new Zone("moltenFault", new MapGenerator("groundZero", 1)){{ //TODO implement - baseLaunchCost = ItemStack.with(Items.copper, 300); - startingItems = ItemStack.with(Items.copper, 200); - conditionWave = 15; - zoneRequirements = new Zone[]{frozenForest}; - blockRequirements = new Block[]{Blocks.copperWall}; - rules = () -> new Rules(){{ - waves = true; - waveTimer = true; - waveSpacing = 60 * 80; - }}; - }};*/ } } diff --git a/core/src/io/anuke/mindustry/core/ContentLoader.java b/core/src/io/anuke/mindustry/core/ContentLoader.java index 1d71ff81db..67bbf503ab 100644 --- a/core/src/io/anuke/mindustry/core/ContentLoader.java +++ b/core/src/io/anuke/mindustry/core/ContentLoader.java @@ -8,20 +8,17 @@ import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.Pixmap; import io.anuke.arc.util.Log; import io.anuke.mindustry.content.*; -import io.anuke.mindustry.entities.type.Player; import io.anuke.mindustry.entities.bullet.Bullet; import io.anuke.mindustry.entities.bullet.BulletType; import io.anuke.mindustry.entities.effect.Fire; import io.anuke.mindustry.entities.effect.Lightning; import io.anuke.mindustry.entities.effect.Puddle; import io.anuke.mindustry.entities.traits.TypeTrait; +import io.anuke.mindustry.entities.type.Player; import io.anuke.mindustry.game.Content; import io.anuke.mindustry.game.ContentList; import io.anuke.mindustry.game.MappableContent; -import io.anuke.mindustry.type.ContentType; -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.type.Liquid; -import io.anuke.mindustry.type.Zone; +import io.anuke.mindustry.type.*; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.LegacyColorMapper; @@ -34,7 +31,7 @@ import static io.anuke.arc.Core.files; @SuppressWarnings("unchecked") public class ContentLoader{ private boolean loaded = false; - private boolean verbose = true; + private boolean verbose = false; private ObjectMap[] contentNameMap = new ObjectMap[ContentType.values().length]; private Array[] contentMap = new Array[ContentType.values().length]; @@ -57,6 +54,10 @@ public class ContentLoader{ new LegacyColorMapper(), }; + public void setVerbose(){ + verbose = true; + } + /**Creates all content types.*/ public void load(){ if(loaded){ @@ -233,6 +234,10 @@ public class ContentLoader{ return getBy(ContentType.zone); } + public Array units(){ + return getBy(ContentType.unit); + } + /** * Registers sync IDs for all types of sync entities. * Do not register units here! diff --git a/core/src/io/anuke/mindustry/core/Control.java b/core/src/io/anuke/mindustry/core/Control.java index e890f7c0a9..5a3f7d47f7 100644 --- a/core/src/io/anuke/mindustry/core/Control.java +++ b/core/src/io/anuke/mindustry/core/Control.java @@ -63,11 +63,6 @@ public class Control implements ApplicationListener{ Draw.scl = 1f / Core.atlas.find("scale_marker").getWidth(); content.initialize(Content::load); - if(Core.atlas.getTextures().size != 1){ - throw new IllegalStateException("Atlas must be exactly one texture. " + - "If more textures are used, the map editor will not display them correctly."); - } - data.load(); Core.settings.setAppName(appName); @@ -115,6 +110,13 @@ public class Control implements ApplicationListener{ //todo high scores for custom maps, as well as other statistics + Events.on(WaveEvent.class, event -> { + if(world.getMap().getHightScore() < state.wave){ + hiscore = true; + world.getMap().setHighScore(state.wave); + } + }); + Events.on(GameOverEvent.class, event -> { state.stats.wavesLasted = state.wave; Effects.shake(5, 6, Core.camera.position.x, Core.camera.position.y); diff --git a/core/src/io/anuke/mindustry/core/Logic.java b/core/src/io/anuke/mindustry/core/Logic.java index 83b3d52f31..6727047b0b 100644 --- a/core/src/io/anuke/mindustry/core/Logic.java +++ b/core/src/io/anuke/mindustry/core/Logic.java @@ -5,15 +5,18 @@ import io.anuke.annotations.Annotations.Remote; import io.anuke.arc.ApplicationListener; import io.anuke.arc.Events; import io.anuke.arc.collection.ObjectSet.ObjectSetIterator; +import io.anuke.arc.util.Time; +import io.anuke.mindustry.content.Fx; +import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.entities.Effects; import io.anuke.mindustry.entities.Entities; import io.anuke.mindustry.entities.EntityGroup; import io.anuke.mindustry.entities.EntityQuery; -import io.anuke.arc.util.Time; -import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.entities.type.TileEntity; -import io.anuke.mindustry.game.EventType.*; +import io.anuke.mindustry.game.EventType.GameOverEvent; +import io.anuke.mindustry.game.EventType.PlayEvent; +import io.anuke.mindustry.game.EventType.ResetEvent; +import io.anuke.mindustry.game.EventType.WaveEvent; import io.anuke.mindustry.game.*; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.type.Item; @@ -58,6 +61,7 @@ public class Logic implements ApplicationListener{ public void play(){ state.set(State.playing); state.wavetime = state.rules.waveSpacing * 2; //grace period of 2x wave time before game starts + state.rules.spawns = world.getMap().getWaves(); Events.fire(new PlayEvent()); } @@ -87,10 +91,10 @@ public class Logic implements ApplicationListener{ } private void checkGameOver(){ - if(!state.rules.pvp && state.teams.get(defaultTeam).cores.size == 0 && !state.gameOver){ + if(state.rules.waves && state.teams.get(defaultTeam).cores.size == 0 && !state.gameOver){ state.gameOver = true; Events.fire(new GameOverEvent(waveTeam)); - }else if(state.rules.pvp){ + }else if(!state.rules.waves){ Team alive = null; for(Team team : Team.all){ diff --git a/core/src/io/anuke/mindustry/core/NetClient.java b/core/src/io/anuke/mindustry/core/NetClient.java index 45da7f1586..6d2b6d8632 100644 --- a/core/src/io/anuke/mindustry/core/NetClient.java +++ b/core/src/io/anuke/mindustry/core/NetClient.java @@ -98,16 +98,15 @@ public class NetClient implements ApplicationListener{ }); Net.handleClient(Disconnect.class, packet -> { + state.set(State.menu); + connecting = false; + Platform.instance.updateRPC(); + if(quiet) return; Time.runTask(3f, ui.loadfrag::hide); - state.set(State.menu); - ui.showError("$disconnect"); - connecting = false; - - Platform.instance.updateRPC(); }); Net.handleClient(WorldStream.class, data -> { diff --git a/core/src/io/anuke/mindustry/core/NetServer.java b/core/src/io/anuke/mindustry/core/NetServer.java index fceb8136af..8c70a164ae 100644 --- a/core/src/io/anuke/mindustry/core/NetServer.java +++ b/core/src/io/anuke/mindustry/core/NetServer.java @@ -233,6 +233,12 @@ public class NetServer implements ApplicationListener{ } public static void onDisconnect(Player player){ + //singleplayer multiplayer wierdness + if(player.con == null){ + player.remove(); + return; + } + if(player.con.hasConnected){ Call.sendMessage("[accent]" + player.name + "[accent] has disconnected."); Call.onPlayerDisconnect(player.id); @@ -573,7 +579,7 @@ public class NetServer implements ApplicationListener{ NetConnection connection = player.con; - if(!connection.isConnected() || !connections.containsKey(connection.id)){ + if(connection == null || !connection.isConnected() || !connections.containsKey(connection.id)){ //player disconnected, call d/c event onDisconnect(player); return; diff --git a/core/src/io/anuke/mindustry/core/Renderer.java b/core/src/io/anuke/mindustry/core/Renderer.java index 5bc7a270ce..c6518854a9 100644 --- a/core/src/io/anuke/mindustry/core/Renderer.java +++ b/core/src/io/anuke/mindustry/core/Renderer.java @@ -13,7 +13,6 @@ import io.anuke.arc.graphics.glutils.FrameBuffer; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Rectangle; import io.anuke.arc.math.geom.Vector2; -import io.anuke.arc.util.ScreenRecorder; import io.anuke.arc.util.Time; import io.anuke.arc.util.Tmp; import io.anuke.arc.util.pooling.Pools; @@ -44,7 +43,7 @@ public class Renderer implements ApplicationListener{ public final MinimapRenderer minimap = new MinimapRenderer(); public final OverlayRenderer overlays = new OverlayRenderer(); - private FrameBuffer shieldBuffer = new FrameBuffer(2, 2); + public FrameBuffer shieldBuffer = new FrameBuffer(2, 2); private Color clearColor; private float targetscale = io.anuke.arc.scene.ui.layout.Unit.dp.scl(4); private float camerascale = targetscale; @@ -131,10 +130,6 @@ public class Renderer implements ApplicationListener{ draw(); } - - if(!ui.chatfrag.chatOpen()){ - ScreenRecorder.record(); //this only does something if CoreGifRecorder is on the class path, which it usually isn't - } } void updateShake(float scale){ @@ -159,6 +154,10 @@ public class Renderer implements ApplicationListener{ graphics.clear(clearColor); + if(graphics.getWidth() >= 2 && graphics.getHeight() >= 2 && (shieldBuffer.getWidth() != graphics.getWidth() || shieldBuffer.getHeight() != graphics.getHeight())){ + shieldBuffer.resize(graphics.getWidth(), graphics.getHeight()); + } + Draw.proj(camera.projection()); blocks.floor.drawFloor(); @@ -200,10 +199,6 @@ public class Renderer implements ApplicationListener{ drawAndInterpolate(playerGroup, p -> true, Player::drawBuildRequests); if(EntityDraw.countInBounds(shieldGroup) > 0){ - if(graphics.getWidth() >= 2 && graphics.getHeight() >= 2 && (shieldBuffer.getWidth() != graphics.getWidth() || shieldBuffer.getHeight() != graphics.getHeight())){ - shieldBuffer.resize(graphics.getWidth(), graphics.getHeight()); - } - Draw.flush(); shieldBuffer.begin(); graphics.clear(Color.CLEAR); @@ -230,7 +225,7 @@ public class Renderer implements ApplicationListener{ private void drawFlyerShadows(){ float trnsX = -12, trnsY = -13; - Draw.color(0, 0, 0, 0.15f); + Draw.color(0, 0, 0, 0.22f); for(EntityGroup group : unitGroups){ if(!group.isEmpty()){ @@ -287,7 +282,7 @@ public class Renderer implements ApplicationListener{ public void clampScale(){ float s = io.anuke.arc.scene.ui.layout.Unit.dp.scl(1f); - targetscale = Mathf.clamp(targetscale, s * 2.5f, Math.round(s * 5)); + targetscale = Mathf.clamp(targetscale, s * 1.5f, Math.round(s * 5)); } } diff --git a/core/src/io/anuke/mindustry/core/UI.java b/core/src/io/anuke/mindustry/core/UI.java index 5bbccaf79a..abf9b8cf9e 100644 --- a/core/src/io/anuke/mindustry/core/UI.java +++ b/core/src/io/anuke/mindustry/core/UI.java @@ -114,22 +114,22 @@ public class UI implements ApplicationListener{ } void loadCursors(){ - int cursorScaling = 3; + int cursorScaling = 1, outlineThickness = 3; Color outlineColor = Color.valueOf("444444"); - drillCursor = Core.graphics.newCursor("drill", cursorScaling, outlineColor); - unloadCursor = Core.graphics.newCursor("unload", cursorScaling, outlineColor); - SystemCursor.arrow.set(Core.graphics.newCursor("cursor", cursorScaling, outlineColor)); - SystemCursor.hand.set(Core.graphics.newCursor("hand", cursorScaling, outlineColor)); - SystemCursor.ibeam.set(Core.graphics.newCursor("ibeam", cursorScaling, outlineColor)); + drillCursor = Core.graphics.newCursor("drill", cursorScaling, outlineColor, outlineThickness); + unloadCursor = Core.graphics.newCursor("unload", cursorScaling, outlineColor, outlineThickness); + SystemCursor.arrow.set(Core.graphics.newCursor("cursor", cursorScaling, outlineColor, outlineThickness)); + SystemCursor.hand.set(Core.graphics.newCursor("hand", cursorScaling, outlineColor, outlineThickness)); + SystemCursor.ibeam.set(Core.graphics.newCursor("ibeam", cursorScaling, outlineColor, outlineThickness)); Core.graphics.restoreCursor(); } void generateFonts(Skin skin){ - generator = new FreeTypeFontGenerator(Core.files.internal("fonts/pixel.ttf")); + generator = new FreeTypeFontGenerator(Core.files.internal("fonts/font.ttf")); FreeTypeFontParameter param = new FreeTypeFontParameter(); - param.size = (int)(14*2 * Math.max(Unit.dp.scl(1f), 0.5f)); + param.size = (int)(9*2 * Math.max(Unit.dp.scl(1f), 0.5f)); param.shadowColor = Color.DARK_GRAY; param.shadowOffsetY = 2; param.incremental = true; diff --git a/core/src/io/anuke/mindustry/core/World.java b/core/src/io/anuke/mindustry/core/World.java index c93e7151aa..822cb3d357 100644 --- a/core/src/io/anuke/mindustry/core/World.java +++ b/core/src/io/anuke/mindustry/core/World.java @@ -23,8 +23,6 @@ import io.anuke.mindustry.game.Team; import io.anuke.mindustry.io.MapIO; import io.anuke.mindustry.maps.Map; import io.anuke.mindustry.maps.MapException; -import io.anuke.mindustry.maps.MapTileData; -import io.anuke.mindustry.maps.MapTileData.TileDataMarker; import io.anuke.mindustry.maps.Maps; import io.anuke.mindustry.maps.generators.Generator; import io.anuke.mindustry.type.ContentType; @@ -235,12 +233,15 @@ public class World implements ApplicationListener{ beginMapLoad(); this.currentMap = map; - int width = map.meta.width, height = map.meta.height; - - createTiles(width, height); - try{ - loadTileData(tiles, MapIO.readTileData(map, true)); + createTiles(map.width, map.height); + for(int x = 0; x < map.width; x++){ + for(int y = 0; y < map.height; y++){ + tiles[x][y] = new Tile(x, y); + } + } + MapIO.readTiles(map, tiles); + prepareTiles(tiles); }catch(Exception e){ Log.err(e); if(!headless){ @@ -260,7 +261,7 @@ public class World implements ApplicationListener{ if(state.teams.get(players[0].getTeam()).cores.size == 0){ ui.showError("$map.nospawn"); invalidMap = true; - }else if(state.rules.pvp){ //pvp maps need two cores to be valid + }else if(state.rules.pvp){ //pvp maps need two cores to be valid invalidMap = true; for(Team team : Team.all){ if(state.teams.get(team).cores.size != 0 && team != players[0].getTeam()){ @@ -416,23 +417,11 @@ public class World implements ApplicationListener{ } /**Loads raw map tile data into a Tile[][] array, setting up multiblocks, cliffs and ores. */ - void loadTileData(Tile[][] tiles, MapTileData data){ - data.position(0, 0); - TileDataMarker marker = data.newDataMarker(); - - for(int y = 0; y < data.height(); y++){ - for(int x = 0; x < data.width(); x++){ - data.read(marker); - - tiles[x][y] = new Tile(x, y, marker.floor, marker.wall == Blocks.part.id ? 0 : marker.wall, marker.rotation, marker.team); - } - } - + void loadTileData(Tile[][] tiles){ prepareTiles(tiles); } public void addDarkness(Tile[][] tiles){ - byte[][] dark = new byte[tiles.length][tiles[0].length]; byte[][] writeBuffer = new byte[tiles.length][tiles[0].length]; diff --git a/core/src/io/anuke/mindustry/editor/DrawOperation.java b/core/src/io/anuke/mindustry/editor/DrawOperation.java index b6b7d13f76..6bc964e465 100755 --- a/core/src/io/anuke/mindustry/editor/DrawOperation.java +++ b/core/src/io/anuke/mindustry/editor/DrawOperation.java @@ -1,72 +1,70 @@ package io.anuke.mindustry.editor; -import io.anuke.arc.collection.Array; -import io.anuke.arc.collection.IntSet; -import io.anuke.arc.util.Pack; -import io.anuke.mindustry.maps.MapTileData; -import io.anuke.mindustry.maps.MapTileData.TileDataMarker; +import io.anuke.annotations.Annotations.Struct; +import io.anuke.arc.collection.LongArray; +import io.anuke.mindustry.game.Team; +import io.anuke.mindustry.gen.TileOp; +import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.blocks.Floor; + +import static io.anuke.mindustry.Vars.content; public class DrawOperation{ - /** - * Data to apply operation to. - */ - private MapTileData data; - /** - * List of per-tile operations that occurred. - */ - private Array operations = new Array<>(); - /** - * Checks for duplicate operations, useful for brushes. - */ - private IntSet checks = new IntSet(); - - public DrawOperation(MapTileData data){ - this.data = data; - } + private LongArray array = new LongArray(); public boolean isEmpty(){ - return operations.size == 0; + return array.isEmpty(); } - public boolean checkDuplicate(short x, short y){ - int i = Pack.shortInt(x, y); - if(checks.contains(i)) return true; - - checks.add(i); - return false; - } - - public void addOperation(TileOperation op){ - operations.add(op); + public void addOperation(long op){ + array.add(op); } public void undo(MapEditor editor){ - for(int i = operations.size - 1; i >= 0; i--){ - TileOperation op = operations.get(i); - data.position(op.x, op.y); - data.write(op.from); - editor.renderer().updatePoint(op.x, op.y); + for(int i = array.size - 1; i >= 0; i--){ + long l = array.get(i); + set(editor, editor.tile(TileOp.x(l), TileOp.y(l)), TileOp.type(l), TileOp.from(l)); } } public void redo(MapEditor editor){ - for(TileOperation op : operations){ - data.position(op.x, op.y); - data.write(op.to); - editor.renderer().updatePoint(op.x, op.y); + for(int i = 0; i < array.size; i++){ + long l = array.get(i); + set(editor, editor.tile(TileOp.x(l), TileOp.y(l)), TileOp.type(l), TileOp.to(l)); } } - public static class TileOperation{ - public short x, y; - public TileDataMarker from; - public TileDataMarker to; + void set(MapEditor editor, Tile tile, byte type, byte to){ + editor.load(() -> { + if(type == OpType.floor.ordinal()){ + tile.setFloor((Floor)content.block(to)); + }else if(type == OpType.block.ordinal()){ + tile.setBlock(content.block(to)); + }else if(type == OpType.rotation.ordinal()){ + tile.setRotation(to); + }else if(type == OpType.team.ordinal()){ + tile.setTeam(Team.all[to]); + }else if(type == OpType.ore.ordinal()){ + tile.setOreByte(to); + } + }); + editor.renderer().updatePoint(tile.x, tile.y); + } - public TileOperation(short x, short y, TileDataMarker from, TileDataMarker to){ - this.x = x; - this.y = y; - this.from = from; - this.to = to; - } + @Struct + class TileOpStruct{ + short x; + short y; + byte type; + byte from; + byte to; + } + + public enum OpType{ + floor, + block, + rotation, + team, + ore } } diff --git a/core/src/io/anuke/mindustry/editor/EditorTile.java b/core/src/io/anuke/mindustry/editor/EditorTile.java new file mode 100644 index 0000000000..b35ae191f6 --- /dev/null +++ b/core/src/io/anuke/mindustry/editor/EditorTile.java @@ -0,0 +1,106 @@ +package io.anuke.mindustry.editor; + +import io.anuke.mindustry.content.Blocks; +import io.anuke.mindustry.editor.DrawOperation.OpType; +import io.anuke.mindustry.game.Team; +import io.anuke.mindustry.gen.TileOp; +import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.blocks.Floor; +import io.anuke.mindustry.world.blocks.OreBlock; +import io.anuke.mindustry.world.modules.ConsumeModule; +import io.anuke.mindustry.world.modules.ItemModule; +import io.anuke.mindustry.world.modules.LiquidModule; +import io.anuke.mindustry.world.modules.PowerModule; + +import static io.anuke.mindustry.Vars.ui; + +public class EditorTile extends Tile{ + + public EditorTile(int x, int y, byte floor, byte wall){ + super(x, y, floor, wall); + } + + @Override + public Team getTeam(){ + return Team.all[getTeamID()]; + } + + @Override + public void setFloor(Floor type){ + if(type instanceof OreBlock){ + //don't place on liquids + if(!floor().isLiquid) setOreByte(type.id); + return; + } + + Block previous = floor(); + Block ore = ore(); + if(previous == type && ore == Blocks.air) return; + super.setFloor(type); + //ore may get nullified so make sure to save editrs + if(ore() != ore){ + op(TileOp.get(x, y, (byte)OpType.ore.ordinal(), ore.id, ore().id)); + } + if(previous != type){ + op(TileOp.get(x, y, (byte)OpType.floor.ordinal(), previous.id, type.id)); + } + } + + @Override + public void setBlock(Block type){ + Block previous = block(); + if(previous == type) return; + super.setBlock(type); + op(TileOp.get(x, y, (byte)OpType.block.ordinal(), previous.id, type.id)); + } + + @Override + public void setTeam(Team team){ + byte previous = getTeamID(); + if(previous == team.ordinal()) return; + super.setTeam(team); + op(TileOp.get(x, y, (byte)OpType.team.ordinal(), previous, (byte)team.ordinal())); + } + + @Override + public void setRotation(byte rotation){ + byte previous = getRotation(); + if(previous == rotation) return; + super.setRotation(rotation); + op(TileOp.get(x, y, (byte)OpType.rotation.ordinal(), previous, rotation)); + } + + @Override + public void setOreByte(byte ore){ + byte previous = getOreByte(); + if(previous == ore) return; + super.setOreByte(ore); + op(TileOp.get(x, y, (byte)OpType.ore.ordinal(), previous, ore)); + } + + @Override + protected void preChanged(){ + super.setTeam(Team.none); + } + + @Override + protected void changed(){ + entity = null; + + Block block = block(); + + if(block.hasEntity()){ + entity = block.newEntity(); + entity.health = block.health; + entity.cons = new ConsumeModule(entity); + if(block.hasItems) entity.items = new ItemModule(); + if(block.hasLiquids) entity.liquids = new LiquidModule(); + if(block.hasPower) entity.power = new PowerModule(); + } + } + + private static void op(long op){ + ui.editor.editor.addTileOp(op); + } +} diff --git a/core/src/io/anuke/mindustry/editor/EditorTool.java b/core/src/io/anuke/mindustry/editor/EditorTool.java index ea40b3eb6d..665d111c4f 100644 --- a/core/src/io/anuke/mindustry/editor/EditorTool.java +++ b/core/src/io/anuke/mindustry/editor/EditorTool.java @@ -7,34 +7,35 @@ import io.anuke.arc.input.KeyCode; import io.anuke.arc.util.Pack; import io.anuke.arc.util.Structs; import io.anuke.mindustry.content.Blocks; -import io.anuke.mindustry.maps.MapTileData; -import io.anuke.mindustry.maps.MapTileData.DataPosition; -import io.anuke.mindustry.maps.MapTileData.TileDataMarker; import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.Pos; +import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.BlockPart; import io.anuke.mindustry.world.blocks.Floor; - -import static io.anuke.mindustry.Vars.*; +import io.anuke.mindustry.world.blocks.OreBlock; public enum EditorTool{ pick{ public void touched(MapEditor editor, int x, int y){ - if(!Structs.inBounds(x, y, editor.getMap().width(), editor.getMap().height())) return; + if(!Structs.inBounds(x, y, editor.width(), editor.height())) return; - byte bf = editor.getMap().read(x, y, DataPosition.floor); - byte bw = editor.getMap().read(x, y, DataPosition.wall); - byte link = editor.getMap().read(x, y, DataPosition.link); + Tile tile = editor.tile(x, y); - if(link != 0){ + byte link = tile.getLinkByte(); + + if(tile.block() instanceof BlockPart && link != 0){ x -= (Pack.leftByte(link) - 8); y -= (Pack.rightByte(link) - 8); - bf = editor.getMap().read(x, y, DataPosition.floor); - bw = editor.getMap().read(x, y, DataPosition.wall); + + tile = editor.tile(x, y); } - Block block = content.block(bw == 0 ? bf : bw); - editor.setDrawBlock(block); - ui.editor.updateSelectedBlock(); + //do not. + if(tile.block() instanceof BlockPart){ + return; + } + + editor.drawBlock = tile.block() == Blocks.air ? tile.ore() == Blocks.air ? tile.floor() : tile.ore() : tile.block(); } }, pencil{ @@ -67,7 +68,7 @@ public enum EditorTool{ @Override public void touched(MapEditor editor, int x, int y){ - editor.draw(x, y, isPaint(), editor.getDrawBlock(), 0.012); + editor.draw(x, y, isPaint(), editor.drawBlock, 0.012); } }, line{ @@ -81,56 +82,57 @@ public enum EditorTool{ } IntArray stack = new IntArray(); - int width; - byte be, dest; - boolean floor; - MapTileData data; + Block dest; + boolean isfloor; + MapEditor data; public void touched(MapEditor editor, int x, int y){ - if(!Structs.inBounds(x, y, editor.getMap().width(), editor.getMap().height())) return; + if(!Structs.inBounds(x, y, editor.width(), editor.height())) return; + Tile tile = editor.tile(x, y); - if(editor.getDrawBlock().isMultiblock()){ + if(editor.drawBlock.isMultiblock()){ //don't fill multiblocks, thanks pencil.touched(editor, x, y); return; } - data = editor.getMap(); + data = editor; + isfloor = editor.drawBlock instanceof Floor; - floor = editor.getDrawBlock() instanceof Floor; + Block floor = tile.floor(); + Block block = tile.block(); + boolean synth = editor.drawBlock.synthetic(); - byte bf = data.read(x, y, DataPosition.floor); - byte bw = data.read(x, y, DataPosition.wall); - boolean synth = editor.getDrawBlock().synthetic(); - byte brt = Pack.byteByte((byte) editor.getDrawRotation(), (byte) editor.getDrawTeam().ordinal()); + Block draw = editor.drawBlock; + dest = draw instanceof OreBlock ? tile.ore() : isfloor ? floor : block; - dest = floor ? bf : bw; - byte draw = editor.getDrawBlock().id; - - if(dest == draw || content.block(bw) instanceof BlockPart || content.block(bw).isMultiblock()){ + if(dest == draw || block == Blocks.part || block.isMultiblock()){ return; } - width = editor.getMap().width(); - int height = editor.getMap().height(); + int width = editor.width(); + int height = editor.height(); IntPositionConsumer writer = (px, py) -> { - TileDataMarker prev = editor.getPrev(px, py, false); + Tile write = editor.tile(px, py); - if(floor){ - data.write(px, py, DataPosition.floor, draw); + if(isfloor){ + write.setFloor((Floor)draw); }else{ - data.write(px, py, DataPosition.wall, draw); + write.setBlock(draw); } if(synth){ - data.write(px, py, DataPosition.rotationTeam, brt); + write.setTeam(editor.drawTeam); } - editor.onWrite(px, py, prev); + if(draw.rotate){ + write.setRotation((byte)editor.rotation); + } }; if(isAlt()){ + //fill all of the same type regardless of borders for(int cx = 0; cx < width; cx++){ for(int cy = 0; cy < height; cy++){ if(eq(cx, cy)){ @@ -139,28 +141,28 @@ public enum EditorTool{ } } }else if(isAlt2()){ + //fill all teams. for(int cx = 0; cx < width; cx++){ for(int cy = 0; cy < height; cy++){ - byte w = data.read(cx, cy, DataPosition.wall); - if(content.block(w).synthetic()){ - TileDataMarker prev = editor.getPrev(cx, cy, false); - data.write(cx, cy, DataPosition.rotationTeam, (byte)editor.getDrawTeam().ordinal()); - editor.onWrite(cx, cy, prev); + Tile write = editor.tile(cx, cy); + if(write.block().synthetic()){ + write.setTeam(editor.drawTeam); } } } }else{ + //normal fill int x1; boolean spanAbove, spanBelow; stack.clear(); - stack.add(asi(x, y)); + stack.add(Pos.get(x, y)); while(stack.size > 0){ int popped = stack.pop(); - x = popped % width; - y = popped / width; + x = Pos.x(popped); + y = Pos.y(popped); x1 = x; while(x1 >= 0 && eq(x1, y)) x1--; @@ -170,14 +172,14 @@ public enum EditorTool{ writer.accept(x1, y); if(!spanAbove && y > 0 && eq(x1, y - 1)){ - stack.add(asi(x1, y - 1)); + stack.add(Pos.get(x1, y - 1)); spanAbove = true; - }else if(spanAbove && y > 0 && eq(x1, y - 1)){ + }else if(spanAbove && eq(x1, y - 1)){ spanAbove = false; } if(!spanBelow && y < height - 1 && eq(x1, y + 1)){ - stack.add(asi(x1, y + 1)); + stack.add(Pos.get(x1, y + 1)); spanBelow = true; }else if(spanBelow && y < height - 1 && eq(x1, y + 1)){ spanBelow = false; @@ -189,15 +191,9 @@ public enum EditorTool{ } boolean eq(int px, int py){ - byte nbf = data.read(px, py, DataPosition.floor); - byte nbw = data.read(px, py, DataPosition.wall); - byte nbe = data.read(px, py, DataPosition.elevation); + Tile tile = data.tile(px, py); - return (floor ? nbf : nbw) == dest && nbe == be; - } - - int asi(int x, int y){ - return x + y * width; + return (data.drawBlock instanceof OreBlock ? tile.ore() : isfloor ? tile.floor() : tile.block()) == dest && !(data.drawBlock instanceof OreBlock && tile.floor().isLiquid); } }, zoom; diff --git a/core/src/io/anuke/mindustry/editor/MapEditor.java b/core/src/io/anuke/mindustry/editor/MapEditor.java index b70ab01467..32b05da7e0 100644 --- a/core/src/io/anuke/mindustry/editor/MapEditor.java +++ b/core/src/io/anuke/mindustry/editor/MapEditor.java @@ -1,88 +1,149 @@ package io.anuke.mindustry.editor; import io.anuke.arc.collection.ObjectMap; +import io.anuke.arc.files.FileHandle; import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Pack; import io.anuke.arc.util.Structs; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.content.Blocks; -import io.anuke.mindustry.editor.DrawOperation.TileOperation; import io.anuke.mindustry.game.Team; -import io.anuke.mindustry.maps.MapTileData; -import io.anuke.mindustry.maps.MapTileData.DataPosition; -import io.anuke.mindustry.maps.MapTileData.TileDataMarker; +import io.anuke.mindustry.gen.TileOp; +import io.anuke.mindustry.io.MapIO; +import io.anuke.mindustry.maps.Map; import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.Floor; -import static io.anuke.mindustry.Vars.content; +import java.io.IOException; public class MapEditor{ public static final int[] brushSizes = {1, 2, 3, 4, 5, 9, 15, 20}; - private MapTileData map; private ObjectMap tags = new ObjectMap<>(); private MapRenderer renderer = new MapRenderer(this); + private Tile[][] tiles; - private int brushSize = 1; - private int rotation; - private Block drawBlock = Blocks.stone; - private Team drawTeam = Team.blue; + private OperationStack stack = new OperationStack(); + private DrawOperation currentOp; + private boolean loading; - public MapTileData getMap(){ - return map; - } + public int brushSize = 1; + public int rotation; + public Block drawBlock = Blocks.stone; + public Team drawTeam = Team.blue; public ObjectMap getTags(){ return tags; } - public void beginEdit(MapTileData map, ObjectMap tags, boolean clear){ - this.map = map; - this.brushSize = 1; - this.tags = tags; + public void beginEdit(int width, int height){ + reset(); - if(clear){ - for(int x = 0; x < map.width(); x++){ - for(int y = 0; y < map.height(); y++){ - map.write(x, y, DataPosition.floor, Blocks.stone.id); + loading = true; + tiles = createTiles(width, height); + renderer.resize(width(), height()); + loading = false; + } + + public void beginEdit(Map map) throws IOException{ + reset(); + + loading = true; + tiles = createTiles(map.width, map.height); + tags.putAll(map.tags); + MapIO.readTiles(map, tiles); + checkLinkedTiles(); + renderer.resize(width(), height()); + loading = false; + } + + public void beginEdit(Tile[][] tiles){ + reset(); + + this.tiles = tiles; + checkLinkedTiles(); + renderer.resize(width(), height()); + } + + //adds missing blockparts + public void checkLinkedTiles(){ + //clear block parts first + for(int x = 0; x < width(); x ++){ + for(int y = 0; y < height(); y++){ + if(tiles[x][y].block() == Blocks.part){ + tiles[x][y].setBlock(Blocks.air); + tiles[x][y].setLinkByte((byte)0); } } } + //set up missing blockparts + for(int x = 0; x < width(); x ++){ + for(int y = 0; y < height(); y ++){ + Block drawBlock = tiles[x][y].block(); + if(drawBlock.isMultiblock()){ + int offsetx = -(drawBlock.size - 1) / 2; + int offsety = -(drawBlock.size - 1) / 2; + for(int dx = 0; dx < drawBlock.size; dx++){ + for(int dy = 0; dy < drawBlock.size; dy++){ + int worldx = dx + offsetx + x; + int worldy = dy + offsety + y; + + if(Structs.inBounds(worldx, worldy, width(), height()) && !(dx + offsetx == 0 && dy + offsety == 0)){ + Tile tile = tiles[worldx][worldy]; + tile.setBlock(Blocks.part); + tile.setLinkByte(Pack.byteByte((byte) (dx + offsetx + 8), (byte) (dy + offsety + 8))); + } + } + } + } + } + } + } + + public void load(Runnable r){ + loading = true; + r.run(); + loading = false; + } + + /**Creates a 2-D array of EditorTiles with stone as the floor block.*/ + public Tile[][] createTiles(int width, int height){ + tiles = new Tile[width][height]; + + for(int x = 0; x < width; x++){ + for(int y = 0; y < height; y++){ + tiles[x][y] = new EditorTile(x, y, Blocks.stone.id, (byte)0); + } + } + return tiles; + } + + public Map createMap(FileHandle file){ + return new Map(file, width(), height(), new ObjectMap<>(tags), true); + } + + private void reset(){ + clearOp(); + brushSize = 1; drawBlock = Blocks.stone; - renderer.resize(map.width(), map.height()); + tags = new ObjectMap<>(); } - public int getDrawRotation(){ - return rotation; + public Tile[][] tiles(){ + return tiles; } - public void setDrawRotation(int rotation){ - this.rotation = rotation; + public Tile tile(int x, int y){ + return tiles[x][y]; } - public Team getDrawTeam(){ - return drawTeam; + public int width(){ + return tiles.length; } - public void setDrawTeam(Team team){ - this.drawTeam = team; - } - - public Block getDrawBlock(){ - return drawBlock; - } - - public void setDrawBlock(Block block){ - this.drawBlock = block; - } - - public int getBrushSize(){ - return brushSize; - } - - public void setBrushSize(int size){ - this.brushSize = size; + public int height(){ + return tiles[0].length; } public void draw(int x, int y, boolean paint){ @@ -94,15 +155,12 @@ public class MapEditor{ } public void draw(int x, int y, boolean paint, Block drawBlock, double chance){ - byte writeID = drawBlock.id; - byte partID = Blocks.part.id; - byte rotationTeam = Pack.byteByte(drawBlock.rotate ? (byte)rotation : 0, drawBlock.synthetic() ? (byte)drawTeam.ordinal() : 0); - boolean isfloor = drawBlock instanceof Floor && drawBlock != Blocks.air; if(drawBlock.isMultiblock()){ - x = Mathf.clamp(x, (drawBlock.size-1)/2, map.width() - drawBlock.size/2 - 1); - y = Mathf.clamp(y, (drawBlock.size-1)/2, map.height() - drawBlock.size/2 - 1); + + x = Mathf.clamp(x, (drawBlock.size-1)/2, width() - drawBlock.size/2 - 1); + y = Mathf.clamp(y, (drawBlock.size-1)/2, height() - drawBlock.size/2 - 1); int offsetx = -(drawBlock.size - 1) / 2; int offsety = -(drawBlock.size - 1) / 2; @@ -113,68 +171,63 @@ public class MapEditor{ int worldx = dx + offsetx + x; int worldy = dy + offsety + y; - if(Structs.inBounds(worldx, worldy, map.width(), map.height())){ - TileDataMarker prev = getPrev(worldx, worldy, false); + if(Structs.inBounds(worldx, worldy, width(), height())){ + Tile tile = tiles[worldx][worldy]; if(i == 1){ - map.write(worldx, worldy, DataPosition.wall, partID); - map.write(worldx, worldy, DataPosition.rotationTeam, rotationTeam); - map.write(worldx, worldy, DataPosition.link, Pack.byteByte((byte) (dx + offsetx + 8), (byte) (dy + offsety + 8))); + tile.setBlock(Blocks.part); + tile.setLinkByte(Pack.byteByte((byte) (dx + offsetx + 8), (byte) (dy + offsety + 8))); }else{ - byte link = map.read(worldx, worldy, DataPosition.link); - byte block = map.read(worldx, worldy, DataPosition.wall); + byte link = tile.getLinkByte(); + Block block = tile.block(); if(link != 0){ removeLinked(worldx - (Pack.leftByte(link) - 8), worldy - (Pack.rightByte(link) - 8)); - }else if(content.block(block).isMultiblock()){ + }else if(block.isMultiblock()){ removeLinked(worldx, worldy); } } - - onWrite(worldx, worldy, prev); } } } } - TileDataMarker prev = getPrev(x, y, false); - - map.write(x, y, DataPosition.wall, writeID); - map.write(x, y, DataPosition.link, (byte) 0); - map.write(x, y, DataPosition.rotationTeam, rotationTeam); - - onWrite(x, y, prev); + Tile tile = tiles[x][y]; + tile.setBlock(drawBlock); + tile.setTeam(drawTeam); }else{ for(int rx = -brushSize; rx <= brushSize; rx++){ for(int ry = -brushSize; ry <= brushSize; ry++){ if(Mathf.dst(rx, ry) <= brushSize - 0.5f && (chance >= 0.999 || Mathf.chance(chance))){ int wx = x + rx, wy = y + ry; - if(wx < 0 || wy < 0 || wx >= map.width() || wy >= map.height() || (paint && !isfloor && content.block(map.read(wx, wy, DataPosition.wall)) == Blocks.air)){ + if(wx < 0 || wy < 0 || wx >= width() || wy >= height() || (paint && !isfloor && tiles[wx][wy].block() == Blocks.air)){ continue; } - TileDataMarker prev = getPrev(wx, wy, true); + Tile tile = tiles[wx][wy]; if(!isfloor){ - byte link = map.read(wx, wy, DataPosition.link); + byte link = tile.getLinkByte(); - if(content.block(map.read(wx, wy, DataPosition.wall)).isMultiblock()){ + if(tile.block().isMultiblock()){ removeLinked(wx, wy); - }else if(link != 0){ + }else if(link != 0 && tiles[x][y].block() == Blocks.part){ removeLinked(wx - (Pack.leftByte(link) - 8), wy - (Pack.rightByte(link) - 8)); } } if(isfloor){ - map.write(wx, wy, DataPosition.floor, writeID); + tile.setFloor((Floor)drawBlock); }else{ - map.write(wx, wy, DataPosition.wall, writeID); - map.write(wx, wy, DataPosition.link, (byte) 0); - map.write(wx, wy, DataPosition.rotationTeam, rotationTeam); + tile.setBlock(drawBlock); + if(drawBlock.synthetic()){ + tile.setTeam(drawTeam); + } + if(drawBlock.rotate){ + tile.setRotation((byte)rotation); + } } - - onWrite(x + rx, y + ry, prev); } } } @@ -182,77 +235,86 @@ public class MapEditor{ } private void removeLinked(int x, int y){ - Block block = content.block(map.read(x, y, DataPosition.wall)); + Block block = tiles[x][y].block(); int offsetx = -(block.size - 1) / 2; int offsety = -(block.size - 1) / 2; for(int dx = 0; dx < block.size; dx++){ for(int dy = 0; dy < block.size; dy++){ int worldx = x + dx + offsetx, worldy = y + dy + offsety; - if(Structs.inBounds(worldx, worldy, map.width(), map.height())){ - TileDataMarker prev = getPrev(worldx, worldy, false); - - map.write(worldx, worldy, DataPosition.link, (byte) 0); - map.write(worldx, worldy, DataPosition.rotationTeam, (byte) 0); - map.write(worldx, worldy, DataPosition.wall, (byte) 0); - - onWrite(worldx, worldy, prev); + if(Structs.inBounds(worldx, worldy, width(), height())){ + tiles[worldx][worldy].setTeam(Team.none); + tiles[worldx][worldy].setBlock(Blocks.air); } } } } - boolean checkDupes(int x, int y){ - return Vars.ui.editor.getView().checkForDuplicates((short) x, (short) y); - } - - void onWrite(int x, int y, TileDataMarker previous){ - if(previous == null){ - renderer.updatePoint(x, y); - return; - } - - TileDataMarker current = map.new TileDataMarker(); - map.position(x, y); - map.read(current); - - Vars.ui.editor.getView().addTileOp(new TileOperation((short) x, (short) y, previous, current)); - renderer.updatePoint(x, y); - } - - TileDataMarker getPrev(int x, int y, boolean checkDupes){ - if(checkDupes && checkDupes(x, y)){ - return null; - }else{ - TileDataMarker marker = map.newDataMarker(); - map.position(x, y); - map.read(marker); - return marker; - } - } - public MapRenderer renderer(){ return renderer; } public void resize(int width, int height){ - MapTileData previous = map; - int offsetX = -(width - previous.width())/2, offsetY = -(height - previous.height())/2; + clearOp(); - map = new MapTileData(width, height); - for(int x = 0; x < map.width(); x++){ - for(int y = 0; y < map.height(); y++){ + Tile[][] previous = tiles; + int offsetX = -(width - width())/2, offsetY = -(height - height())/2; + loading = true; + + tiles = new Tile[width][height]; + for(int x = 0; x < width; x++){ + for(int y = 0; y < height; y++){ int px = offsetX + x, py = offsetY + y; - if(Structs.inBounds(px, py, previous.width(), previous.height())){ - map.write(x, y, DataPosition.floor, previous.read(px, py, DataPosition.floor)); - map.write(x, y, DataPosition.wall, previous.read(px, py, DataPosition.wall)); - map.write(x, y, DataPosition.link, previous.read(px, py, DataPosition.link)); - map.write(x, y, DataPosition.rotationTeam, previous.read(px, py, DataPosition.rotationTeam)); + if(Structs.inBounds(px, py, previous.length, previous[0].length)){ + tiles[x][y] = previous[px][py]; + tiles[x][y].x = (short)x; + tiles[x][y].y = (short)y; }else{ - map.write(x, y, DataPosition.floor, Blocks.stone.id); + tiles[x][y] = new EditorTile(x, y, Blocks.stone.id, (byte)0); } } } + renderer.resize(width, height); + loading = false; } -} + + public void clearOp(){ + stack.clear(); + } + + public void undo(){ + if(stack.canUndo()){ + stack.undo(this); + } + } + + public void redo(){ + if(stack.canRedo()){ + stack.redo(this); + } + } + + public boolean canUndo(){ + return stack.canUndo(); + } + + public boolean canRedo(){ + return stack.canRedo(); + } + + public void flushOp(){ + if(currentOp == null || currentOp.isEmpty()) return; + stack.add(currentOp); + currentOp = null; + } + + public void addTileOp(long data){ + if(loading) return; + + if(currentOp == null) currentOp = new DrawOperation(); + currentOp.addOperation(data); + + renderer.updatePoint(TileOp.x(data), TileOp.y(data)); + } +} \ No newline at end of file diff --git a/core/src/io/anuke/mindustry/editor/MapEditorDialog.java b/core/src/io/anuke/mindustry/editor/MapEditorDialog.java index ab494b556a..966f979a92 100644 --- a/core/src/io/anuke/mindustry/editor/MapEditorDialog.java +++ b/core/src/io/anuke/mindustry/editor/MapEditorDialog.java @@ -2,7 +2,6 @@ package io.anuke.mindustry.editor; import io.anuke.arc.Core; import io.anuke.arc.collection.Array; -import io.anuke.arc.collection.ObjectMap; import io.anuke.arc.files.FileHandle; import io.anuke.arc.function.Consumer; import io.anuke.arc.graphics.Color; @@ -23,33 +22,28 @@ import io.anuke.mindustry.core.Platform; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.io.MapIO; import io.anuke.mindustry.maps.Map; -import io.anuke.mindustry.maps.MapMeta; -import io.anuke.mindustry.maps.MapTileData; import io.anuke.mindustry.ui.dialogs.FloatingDialog; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Block.Icon; +import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.OreBlock; import io.anuke.mindustry.world.blocks.storage.CoreBlock; -import java.io.DataInputStream; -import java.io.InputStream; - import static io.anuke.mindustry.Vars.*; public class MapEditorDialog extends Dialog implements Disposable{ - private MapEditor editor; + public final MapEditor editor; private MapView view; private MapInfoDialog infoDialog; private MapLoadDialog loadDialog; private MapResizeDialog resizeDialog; + private MapGenerateDialog generateDialog; private ScrollPane pane; private FloatingDialog menu; private boolean saved = false; private boolean shownWithMap = false; private Array blocksOut = new Array<>(); - private ButtonGroup blockgroup; - public MapEditorDialog(){ super("", "dialog"); @@ -57,8 +51,8 @@ public class MapEditorDialog extends Dialog implements Disposable{ editor = new MapEditor(); view = new MapView(editor); - infoDialog = new MapInfoDialog(editor); + generateDialog = new MapGenerateDialog(editor); menu = new FloatingDialog("$menu"); menu.addCloseButton(); @@ -69,15 +63,20 @@ public class MapEditorDialog extends Dialog implements Disposable{ menu.cont.table(t -> { t.defaults().size(swidth, 60f).padBottom(5).padRight(5).padLeft(5); - t.addImageTextButton("$editor.savemap", "icon-floppy-16", isize, this::save).size(swidth * 2f + 10, 60f).colspan(2); - - t.row(); + t.addImageTextButton("$editor.savemap", "icon-floppy-16", isize, this::save); t.addImageTextButton("$editor.mapinfo", "icon-pencil", isize, () -> { infoDialog.show(); menu.hide(); }); + t.row(); + + t.addImageTextButton("$editor.generate", "icon-editor", isize, () -> { + generateDialog.show(); + menu.hide(); + }); + t.addImageTextButton("$editor.resize", "icon-resize", isize, () -> { resizeDialog.show(); menu.hide(); @@ -89,17 +88,12 @@ public class MapEditorDialog extends Dialog implements Disposable{ createDialog("$editor.import", "$editor.importmap", "$editor.importmap.description", "icon-load-map", (Runnable) loadDialog::show, "$editor.importfile", "$editor.importfile.description", "icon-file", (Runnable) () -> - Platform.instance.showFileChooser("$loadimage", "Map Files", file -> ui.loadAnd(() -> { + Platform.instance.showFileChooser("$editor.loadmap", "Map Files", file -> ui.loadAnd(() -> { try{ - DataInputStream stream = new DataInputStream(file.read()); - - MapMeta meta = MapIO.readMapMeta(stream); - MapTileData data = MapIO.readTileData(stream, meta, false); - - editor.beginEdit(data, meta.tags, false); - view.clearStack(); + //TODO what if it's an image? users should be warned for their stupidity + editor.beginEdit(MapIO.readMap(file, true)); }catch(Exception e){ - ui.showError(Core.bundle.format("editor.errorimageload", Strings.parseException(e, false))); + ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, false))); Log.err(e); } }), true, mapExtension), @@ -108,39 +102,32 @@ public class MapEditorDialog extends Dialog implements Disposable{ Platform.instance.showFileChooser("$loadimage", "Image Files", file -> ui.loadAnd(() -> { try{ - MapTileData data = MapIO.readLegacyPixmap(new Pixmap(file)); - - editor.beginEdit(data, editor.getTags(), false); - view.clearStack(); + Pixmap pixmap = new Pixmap(file); + Tile[][] tiles = editor.createTiles(pixmap.getWidth(), pixmap.getHeight()); + editor.load(() -> MapIO.readLegacyPixmap(pixmap, tiles)); + editor.beginEdit(tiles); }catch (Exception e){ - ui.showError(Core.bundle.format("editor.errorimageload", Strings.parseException(e, false))); + ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, false))); Log.err(e); } - }), true, "png") - )); + }), true, "png"))); - t.addImageTextButton("$editor.export", "icon-save-map", isize, () -> createDialog("$editor.export", - "$editor.exportfile", "$editor.exportfile.description", "icon-file", (Runnable) () -> - Platform.instance.showFileChooser("$saveimage", "Map Files", file -> { + t.addImageTextButton("$editor.export", "icon-save-map", isize, () -> + Platform.instance.showFileChooser("$editor.savemap", "Map Files", file -> { file = file.parent().child(file.nameWithoutExtension() + "." + mapExtension); FileHandle result = file; ui.loadAnd(() -> { - try{ if(!editor.getTags().containsKey("name")){ editor.getTags().put("name", result.nameWithoutExtension()); } - MapIO.writeMap(result.write(false), editor.getTags(), editor.getMap()); + MapIO.writeMap(result, editor.createMap(result), editor.tiles()); }catch(Exception e){ - ui.showError(Core.bundle.format("editor.errorimagesave", Strings.parseException(e, false))); + ui.showError(Core.bundle.format("editor.errorsave", Strings.parseException(e, false))); Log.err(e); } }); - }, false, mapExtension))); - - t.row(); - - t.row(); + }, false, mapExtension)); }); menu.cont.row(); @@ -151,24 +138,19 @@ public class MapEditorDialog extends Dialog implements Disposable{ }).padTop(-5).size(swidth * 2f + 10, 60f); resizeDialog = new MapResizeDialog(editor, (x, y) -> { - if(!(editor.getMap().width() == x && editor.getMap().height() == y)){ + if(!(editor.width() == x && editor.height() == y)){ ui.loadAnd(() -> { editor.resize(x, y); - view.clearStack(); }); } }); loadDialog = new MapLoadDialog(map -> ui.loadAnd(() -> { - try(DataInputStream stream = new DataInputStream(map.stream.get())){ - MapMeta meta = MapIO.readMapMeta(stream); - MapTileData data = MapIO.readTileData(stream, meta, false); - - editor.beginEdit(data, meta.tags, false); - view.clearStack(); + try{ + editor.beginEdit(map); }catch(Exception e){ - ui.showError(Core.bundle.format("editor.errorimageload", Strings.parseException(e, false))); + ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, false))); Log.err(e); } })); @@ -200,10 +182,10 @@ public class MapEditorDialog extends Dialog implements Disposable{ shown(() -> { saved = true; Platform.instance.beginForceLandscape(); - view.clearStack(); + editor.clearOp(); Core.scene.setScrollFocus(view); if(!shownWithMap){ - editor.beginEdit(new MapTileData(200, 200), new ObjectMap<>(), true); + editor.beginEdit(200, 200); } shownWithMap = false; @@ -211,6 +193,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ }); hidden(() -> { + editor.clearOp(); Platform.instance.updateRPC(); Platform.instance.endForceLandscape(); }); @@ -222,16 +205,17 @@ public class MapEditorDialog extends Dialog implements Disposable{ } private void save(){ - String name = editor.getTags().get("name", ""); + String name = editor.getTags().get("name", "").trim(); if(name.isEmpty()){ - ui.showError("$editor.save.noname"); + infoDialog.show(); + Core.app.post(() -> ui.showError("$editor.save.noname")); }else{ - Map map = world.maps.getByName(name); + Map map = world.maps.all().find(m -> m.name().equals(name)); if(map != null && !map.custom){ ui.showError("$editor.save.overwrite"); }else{ - world.maps.saveMap(name, editor.getMap(), editor.getTags()); + world.maps.saveMap(editor.getTags(), editor.tiles()); ui.showInfoFade("$editor.saved"); } } @@ -293,18 +277,16 @@ public class MapEditorDialog extends Dialog implements Disposable{ editor.renderer().dispose(); } - public void beginEditMap(InputStream is){ + public void beginEditMap(FileHandle file){ ui.loadAnd(() -> { try{ + Map map = MapIO.readMap(file, true); shownWithMap = true; - DataInputStream stream = new DataInputStream(is); - MapMeta meta = MapIO.readMapMeta(stream); - editor.beginEdit(MapIO.readTileData(stream, meta, false), meta.tags, false); - is.close(); + editor.beginEdit(map); show(); }catch(Exception e){ Log.err(e); - ui.showError(Core.bundle.format("editor.errorimageload", Strings.parseException(e, false))); + ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, false))); } }); } @@ -317,16 +299,6 @@ public class MapEditorDialog extends Dialog implements Disposable{ saved = false; } - public void updateSelectedBlock(){ - Block block = editor.getDrawBlock(); - for(int j = 0; j < Vars.content.blocks().size; j++){ - if(block.id == j && j < blockgroup.getButtons().size){ - blockgroup.getButtons().get(j).setChecked(true); - break; - } - } - } - public boolean hasPane(){ return Core.scene.getScrollFocus() == pane || Core.scene.getKeyboardFocus() != this; } @@ -370,15 +342,15 @@ public class MapEditorDialog extends Dialog implements Disposable{ tools.row(); - ImageButton undo = tools.addImageButton("icon-undo", "clear", 16 * 2f, () -> view.undo()).get(); - ImageButton redo = tools.addImageButton("icon-redo", "clear", 16 * 2f, () -> view.redo()).get(); + ImageButton undo = tools.addImageButton("icon-undo", "clear", 16 * 2f, editor::undo).get(); + ImageButton redo = tools.addImageButton("icon-redo", "clear", 16 * 2f, editor::redo).get(); addTool.accept(EditorTool.pick); tools.row(); - undo.setDisabled(() -> !view.getStack().canUndo()); - redo.setDisabled(() -> !view.getStack().canRedo()); + undo.setDisabled(() -> !editor.canUndo()); + redo.setDisabled(() -> !editor.canRedo()); undo.update(() -> undo.getImage().setColor(undo.isDisabled() ? Color.GRAY : Color.WHITE)); redo.update(() -> redo.getImage().setColor(redo.isDisabled() ? Color.GRAY : Color.WHITE)); @@ -393,9 +365,9 @@ public class MapEditorDialog extends Dialog implements Disposable{ addTool.accept(EditorTool.fill); addTool.accept(EditorTool.spray); - ImageButton rotate = tools.addImageButton("icon-arrow-16", "clear", 16 * 2f, () -> editor.setDrawRotation((editor.getDrawRotation() + 1) % 4)).get(); + ImageButton rotate = tools.addImageButton("icon-arrow-16", "clear", 16 * 2f, () -> editor.rotation = (editor.rotation + 1) % 4).get(); rotate.getImage().update(() -> { - rotate.getImage().setRotation(editor.getDrawRotation() * 90); + rotate.getImage().setRotation(editor.rotation * 90); rotate.getImage().setOrigin(Align.center); }); @@ -415,8 +387,8 @@ public class MapEditorDialog extends Dialog implements Disposable{ button.margin(4f); button.getImageCell().grow(); button.getStyle().imageUpColor = team.color; - button.clicked(() -> editor.setDrawTeam(team)); - button.update(() -> button.setChecked(editor.getDrawTeam() == team)); + button.clicked(() -> editor.drawTeam = team); + button.update(() -> button.setChecked(editor.drawTeam == team)); teamgroup.add(button); tools.add(button); @@ -429,7 +401,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ mid.table("underline", t -> { Slider slider = new Slider(0, MapEditor.brushSizes.length - 1, 1, false); - slider.moved(f -> editor.setBrushSize(MapEditor.brushSizes[(int) (float) f])); + slider.moved(f -> editor.brushSize = MapEditor.brushSizes[(int) (float) f]); t.top(); t.add("$editor.brush"); @@ -456,22 +428,28 @@ public class MapEditorDialog extends Dialog implements Disposable{ } } + if(Core.input.keyTap(KeyCode.ESCAPE)){ + if(!menu.isShown()){ + menu.show(); + } + } + if(Core.input.keyTap(KeyCode.R)){ - editor.setDrawRotation((editor.getDrawRotation() + 1) % 4); + editor.rotation = Mathf.mod(editor.rotation + 1, 4); } if(Core.input.keyTap(KeyCode.E)){ - editor.setDrawRotation(Mathf.mod((editor.getDrawRotation() + 1), 4)); + editor.rotation = Mathf.mod(editor.rotation - 1, 4); } //ctrl keys (undo, redo, save) if(UIUtils.ctrl()){ if(Core.input.keyTap(KeyCode.Z)){ - view.undo(); + editor.undo(); } if(Core.input.keyTap(KeyCode.Y)){ - view.redo(); + editor.redo(); } if(Core.input.keyTap(KeyCode.S)){ @@ -498,7 +476,6 @@ public class MapEditorDialog extends Dialog implements Disposable{ pane.setFadeScrollBars(false); pane.setOverscroll(true, false); ButtonGroup group = new ButtonGroup<>(); - blockgroup = group; int i = 0; @@ -521,9 +498,9 @@ public class MapEditorDialog extends Dialog implements Disposable{ ImageButton button = new ImageButton("white", "clear-toggle"); button.getStyle().imageUp = new TextureRegionDrawable(region); - button.clicked(() -> editor.setDrawBlock(block)); + button.clicked(() -> editor.drawBlock = block); button.resizeImage(8 * 4f); - button.update(() -> button.setChecked(editor.getDrawBlock() == block)); + button.update(() -> button.setChecked(editor.drawBlock == block)); group.add(button); content.add(button).size(50f); @@ -534,7 +511,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ group.getButtons().get(2).setChecked(true); - table.table("underline", extra -> extra.labelWrap(() -> editor.getDrawBlock().localizedName).width(200f).center()).growX(); + table.table("underline", extra -> extra.labelWrap(() -> editor.drawBlock.localizedName).width(200f).center()).growX(); table.row(); table.add(pane).growY().fillX(); } diff --git a/core/src/io/anuke/mindustry/editor/MapGenerateDialog.java b/core/src/io/anuke/mindustry/editor/MapGenerateDialog.java new file mode 100644 index 0000000000..bae20da504 --- /dev/null +++ b/core/src/io/anuke/mindustry/editor/MapGenerateDialog.java @@ -0,0 +1,317 @@ +package io.anuke.mindustry.editor; + +import io.anuke.arc.Core; +import io.anuke.arc.collection.Array; +import io.anuke.arc.function.Supplier; +import io.anuke.arc.graphics.Pixmap; +import io.anuke.arc.graphics.Pixmap.Format; +import io.anuke.arc.graphics.Texture; +import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.arc.util.async.AsyncExecutor; +import io.anuke.arc.util.async.AsyncResult; +import io.anuke.mindustry.content.Blocks; +import io.anuke.mindustry.editor.generation.*; +import io.anuke.mindustry.editor.generation.GenerateFilter.GenerateInput; +import io.anuke.mindustry.game.Team; +import io.anuke.mindustry.graphics.Pal; +import io.anuke.mindustry.io.MapIO; +import io.anuke.mindustry.ui.BorderImage; +import io.anuke.mindustry.ui.dialogs.FloatingDialog; +import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.blocks.Floor; + +import static io.anuke.mindustry.Vars.mobile; + +@SuppressWarnings("unchecked") +public class MapGenerateDialog extends FloatingDialog{ + private final MapEditor editor; + private Pixmap pixmap; + private Texture texture; + private GenerateInput input = new GenerateInput(); + private Array filters = new Array<>(); + private int scaling = mobile ? 3 : 1; + private Supplier[] filterTypes = new Supplier[]{NoiseFilter::new, ScatterFilter::new, TerrainFilter::new, DistortFilter::new, RiverNoiseFilter::new, OreFilter::new}; + private Table filterTable; + + private AsyncExecutor executor = new AsyncExecutor(1); + private AsyncResult result; + private boolean generating; + private DummyTile returnTile = new DummyTile(); + + private DummyTile[][] buffer1, buffer2; + + public MapGenerateDialog(MapEditor editor){ + super("$editor.generate"); + this.editor = editor; + + shown(this::setup); + addCloseButton(); + buttons.addButton("$editor.apply", () -> { + apply(); + hide(); + }).size(160f, 64f); + buttons.addButton("$editor.randomize", () -> { + for(GenerateFilter filter : filters){ + filter.randomize(); + } + update(); + }).size(160f, 64f); + + buttons.addImageTextButton("$add", "icon-add", 14*2, this::showAdd).height(64f).width(140f); + } + + void setup(){ + if(pixmap != null){ + pixmap.dispose(); + texture.dispose(); + pixmap = null; + texture = null; + } + + pixmap = new Pixmap(editor.width() / scaling, editor.height() / scaling, Format.RGBA8888); + texture = new Texture(pixmap); + + cont.clear(); + cont.table("flat", t -> { + t.margin(8f); + t.add(new BorderImage(texture)).size(400f).padRight(6); + t.pane(p -> filterTable = p).width(300f).get().setScrollingDisabled(true, false); + }).grow(); + + update(); + + buffer1 = create(); + buffer2 = create(); + + rebuildFilters(); + } + + DummyTile[][] create(){ + DummyTile[][] out = new DummyTile[editor.width() / scaling][editor.height() / scaling]; + + for(int x = 0; x < out.length; x++){ + for(int y = 0; y < out[0].length; y++){ + out[x][y] = new DummyTile(); + } + } + return out; + } + + void rebuildFilters(){ + filterTable.clearChildren(); + filterTable.top(); + + for(GenerateFilter filter : filters){ + filterTable.table(t -> { + t.add(filter.name()).padTop(5).color(Pal.accent).growX().left(); + + t.row(); + + t.table(b -> { + b.left(); + b.defaults().size(50f); + b.addImageButton("icon-refresh", 14*2, () -> { + filter.randomize(); + update(); + }); + + b.addImageButton("icon-arrow-up", 10*2, () -> { + int idx = filters.indexOf(filter); + filters.swap(idx, Math.max(0, idx - 1)); + rebuildFilters(); + update(); + }); + b.addImageButton("icon-arrow-down", 10*2, () -> { + int idx = filters.indexOf(filter); + filters.swap(idx, Math.min(filters.size-1, idx + 1)); + rebuildFilters(); + update(); + }); + b.addImageButton("icon-trash", 14*2, () -> { + filters.remove(filter); + rebuildFilters(); + update(); + }); + }).growX(); + }).fillX(); + filterTable.row(); + filterTable.table("underline", f -> { + f.left(); + for(FilterOption option : filter.options){ + option.changed = this::update; + + f.table(t -> { + t.left(); + option.build(t); + }).growX().left(); + f.row(); + } + }).pad(3).padTop(0).width(280f); + filterTable.row(); + } + + if(filters.isEmpty()){ + filterTable.add("$filters.empty").wrap().width(200f); + } + } + + void showAdd(){ + FloatingDialog selection = new FloatingDialog("$add"); + selection.setFillParent(false); + selection.cont.defaults().size(210f, 60f); + int i = 0; + for(Supplier gen : filterTypes){ + GenerateFilter filter = gen.get(); + selection.cont.addButton(filter.name(), () -> { + filters.add(filter); + rebuildFilters(); + update(); + selection.hide(); + }); + if(++i % 2 == 0) selection.cont.row(); + } + + selection.addCloseButton(); + selection.show(); + } + + DummyTile dset(Tile tile){ + returnTile.set(tile); + return returnTile; + } + + void apply(){ + if(result != null){ + result.get(); + } + + //writeback buffer + DummyTile[][] writeTiles = new DummyTile[editor.width()][editor.height()]; + + for(int x = 0; x < editor.width(); x++){ + for(int y = 0; y < editor.height(); y++){ + writeTiles[x][y] = new DummyTile(); + } + } + + for(GenerateFilter filter : filters){ + input.setFilter(filter, (x, y) -> dset(editor.tile(x, y))); + //write to buffer + for(int x = 0; x < editor.width(); x++){ + for(int y = 0; y < editor.height(); y++){ + Tile tile = editor.tile(x, y); + input.begin(editor, x, y, tile.floor(), tile.block(), tile.ore()); + filter.apply(input); + writeTiles[x][y].set(input.floor, input.block, input.ore, tile.getTeam(), tile.getRotation()); + } + } + + editor.load(() -> { + //read from buffer back into tiles + for(int x = 0; x < editor.width(); x++){ + for(int y = 0; y < editor.height(); y++){ + Tile tile = editor.tile(x, y); + DummyTile write = writeTiles[x][y]; + + tile.setRotation((byte)write.rotation); + tile.setFloor((Floor)write.floor); + tile.setBlock(write.block); + tile.setTeam(write.team); + tile.setOre(write.ore); + } + } + }); + } + + //reset undo stack as generation... messes things up + editor.load(editor::checkLinkedTiles); + editor.renderer().updateAll(); + editor.clearOp(); + } + + void update(){ + + if(generating){ + return; + } + + Array copy = new Array<>(filters); + + result = executor.submit(() -> { + generating = true; + + if(!filters.isEmpty()){ + //write to buffer1 for reading + for(int px = 0; px < pixmap.getWidth(); px++){ + for(int py = 0; py < pixmap.getHeight(); py++){ + buffer1[px][py].set(editor.tile(px * scaling, py * scaling)); + } + } + } + + for(GenerateFilter filter : copy){ + input.setFilter(filter, (x, y) -> buffer1[x][y]); + //read from buffer1 and write to buffer2 + for(int px = 0; px < pixmap.getWidth(); px++){ + for(int py = 0; py < pixmap.getHeight(); py++){ + int x = px*scaling, y = py*scaling; + DummyTile tile = buffer1[px][py]; + input.begin(editor, x, y, tile.floor, tile.block, tile.ore); + filter.apply(input); + buffer2[px][py].set(input.floor, input.block, input.ore, tile.team, tile.rotation); + } + } + for(int px = 0; px < pixmap.getWidth(); px++){ + for(int py = 0; py < pixmap.getHeight(); py++){ + buffer1[px][py].set(buffer2[px][py]); + } + } + } + + for(int px = 0; px < pixmap.getWidth(); px++){ + for(int py = 0; py < pixmap.getHeight(); py++){ + int color; + //get result from buffer1 if there's filters left, otherwise get from editor directly + if(filters.isEmpty()){ + Tile tile = editor.tile(px * scaling, py * scaling); + color = MapIO.colorFor(tile.floor(), tile.block(), tile.ore(), Team.none); + }else{ + DummyTile tile = buffer1[px][py]; + color = MapIO.colorFor(tile.floor, tile.block, tile.ore, Team.none); + } + pixmap.drawPixel(px, pixmap.getHeight() - 1 - py, color); + } + } + + Core.app.post(() -> { + texture.draw(pixmap, 0, 0); + generating = false; + }); + return null; + }); + } + + public static class DummyTile{ + public Block block = Blocks.air, ore = Blocks.air, floor = Blocks.air; + public Team team = Team.none; + public int rotation; + + void set(Block floor, Block wall, Block ore, Team team, int rotation){ + this.floor = floor; + this.block = wall; + this.ore = ore; + this.team = team; + this.rotation = rotation; + } + + void set(DummyTile other){ + set(other.floor, other.block, other.ore, other.team, other.rotation); + } + + void set(Tile other){ + set(other.floor(), other.block(), other.ore(), other.getTeam(), other.getRotation()); + } + + } +} diff --git a/core/src/io/anuke/mindustry/editor/MapInfoDialog.java b/core/src/io/anuke/mindustry/editor/MapInfoDialog.java index f1e81e7ab0..a422552312 100644 --- a/core/src/io/anuke/mindustry/editor/MapInfoDialog.java +++ b/core/src/io/anuke/mindustry/editor/MapInfoDialog.java @@ -9,22 +9,16 @@ import io.anuke.mindustry.ui.dialogs.FloatingDialog; public class MapInfoDialog extends FloatingDialog{ private final MapEditor editor; - - private TextArea description; - private TextField author; - private TextField name; + private final WaveInfoDialog waveinfo; public MapInfoDialog(MapEditor editor){ super("$editor.mapinfo"); this.editor = editor; + this.waveinfo = new WaveInfoDialog(editor); addCloseButton(); shown(this::setup); - - hidden(() -> { - - }); } private void setup(){ @@ -36,7 +30,7 @@ public class MapInfoDialog extends FloatingDialog{ cont.defaults().padTop(15); - name = cont.addField(tags.get("name", ""), text -> { + TextField name = cont.addField(tags.get("name", ""), text -> { tags.put("name", text); }).size(400, 55f).get(); name.setMessageText("$unknown"); @@ -45,7 +39,7 @@ public class MapInfoDialog extends FloatingDialog{ cont.add("$editor.description").padRight(8).left(); - description = cont.addArea(tags.get("description", ""), "textarea", text -> { + TextArea description = cont.addArea(tags.get("description", ""), "textarea", text -> { tags.put("description", text); }).size(400f, 140f).get(); @@ -53,13 +47,22 @@ public class MapInfoDialog extends FloatingDialog{ cont.add("$editor.author").padRight(8).left(); - author = cont.addField(tags.get("author", Core.settings.getString("mapAuthor", "")), text -> { + TextField author = cont.addField(tags.get("author", Core.settings.getString("mapAuthor", "")), text -> { tags.put("author", text); Core.settings.put("mapAuthor", text); Core.settings.save(); }).size(400, 55f).get(); author.setMessageText("$unknown"); + cont.row(); + cont.add("$editor.waves").padRight(8).left(); + cont.table(t -> { + t.add().growX(); + t.label(() -> tags.containsKey("waves") ? "" : Core.bundle.get("editor.default")).left(); + t.add().growX(); + t.addButton("$edit", waveinfo::show).growY().width(200f); + }).size(400, 55f); + name.change(); description.change(); author.change(); diff --git a/core/src/io/anuke/mindustry/editor/MapLoadDialog.java b/core/src/io/anuke/mindustry/editor/MapLoadDialog.java index 0955dcdc6a..edca8d7868 100644 --- a/core/src/io/anuke/mindustry/editor/MapLoadDialog.java +++ b/core/src/io/anuke/mindustry/editor/MapLoadDialog.java @@ -56,7 +56,7 @@ public class MapLoadDialog extends FloatingDialog{ for(Map map : world.maps.all()){ - TextButton button = new TextButton(map.getDisplayName(), "toggle"); + TextButton button = new TextButton(map.name(), "toggle"); button.add(new BorderImage(map.texture, 2f).setScaling(Scaling.fit)).size(16 * 4f); button.getCells().reverse(); button.clicked(() -> selected = map); diff --git a/core/src/io/anuke/mindustry/editor/MapRenderer.java b/core/src/io/anuke/mindustry/editor/MapRenderer.java index 5917cd67a2..65aa4fa56a 100644 --- a/core/src/io/anuke/mindustry/editor/MapRenderer.java +++ b/core/src/io/anuke/mindustry/editor/MapRenderer.java @@ -4,19 +4,17 @@ import io.anuke.arc.Core; import io.anuke.arc.collection.IntSet; import io.anuke.arc.collection.IntSet.IntSetIterator; import io.anuke.arc.graphics.Color; +import io.anuke.arc.graphics.Texture; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Disposable; -import io.anuke.arc.util.Pack; import io.anuke.mindustry.content.Blocks; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.graphics.IndexedRenderer; -import io.anuke.mindustry.maps.MapTileData.DataPosition; import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.Block.Icon; +import io.anuke.mindustry.world.Tile; -import static io.anuke.mindustry.Vars.content; import static io.anuke.mindustry.Vars.tilesize; public class MapRenderer implements Disposable{ @@ -26,9 +24,11 @@ public class MapRenderer implements Disposable{ private IntSet delayedUpdates = new IntSet(); private MapEditor editor; private int width, height; + private Texture texture; public MapRenderer(MapEditor editor){ this.editor = editor; + texture = Core.atlas.find("clear-editor").getTexture(); } public void resize(int width, int height){ @@ -52,7 +52,6 @@ public class MapRenderer implements Disposable{ updateAll(); } - public void draw(float tx, float ty, float tw, float th){ Draw.flush(); @@ -80,7 +79,7 @@ public class MapRenderer implements Disposable{ mesh.getTransformMatrix().setToTranslation(tx, ty).scale(tw / (width * tilesize), th / (height * tilesize)); mesh.setProjectionMatrix(Draw.proj()); - mesh.render(Core.atlas.getTextures().first()); + mesh.render(texture); } } } @@ -101,27 +100,24 @@ public class MapRenderer implements Disposable{ private void render(int wx, int wy){ int x = wx / chunksize, y = wy / chunksize; IndexedRenderer mesh = chunks[x][y]; - byte bf = editor.getMap().read(wx, wy, DataPosition.floor); - byte bw = editor.getMap().read(wx, wy, DataPosition.wall); - byte btr = editor.getMap().read(wx, wy, DataPosition.rotationTeam); - byte rotation = Pack.leftByte(btr); - Team team = Team.all[Pack.rightByte(btr)]; + Tile tile = editor.tiles()[wx][wy]; - Block floor = content.block(bf); - Block wall = content.block(bw); + Team team = tile.getTeam(); + Block floor = tile.floor(); + Block wall = tile.block(); TextureRegion region; int idxWall = (wx % chunksize) + (wy % chunksize) * chunksize; int idxDecal = (wx % chunksize) + (wy % chunksize) * chunksize + chunksize * chunksize; - if(bw != 0 && (wall.synthetic() || wall == Blocks.part)){ - region = wall.icon(Icon.full) == Core.atlas.find("____") ? Core.atlas.find("clear") : wall.icon(Icon.full); + if(wall != Blocks.air && (wall.synthetic() || wall == Blocks.part)){ + region = !Core.atlas.isFound(wall.editorIcon()) ? Core.atlas.find("clear-editor") : wall.editorIcon(); if(wall.rotate){ mesh.draw(idxWall, region, wx * tilesize + wall.offset(), wy * tilesize + wall.offset(), - region.getWidth() * Draw.scl, region.getHeight() * Draw.scl, rotation * 90 - 90); + region.getWidth() * Draw.scl, region.getHeight() * Draw.scl, tile.getRotation() * 90 - 90); }else{ mesh.draw(idxWall, region, wx * tilesize + wall.offset() + (tilesize - region.getWidth() * Draw.scl)/2f, @@ -129,7 +125,7 @@ public class MapRenderer implements Disposable{ region.getWidth() * Draw.scl, region.getHeight() * Draw.scl); } }else{ - region = floor.variantRegions()[Mathf.randomSeed(idxWall, 0, floor.variantRegions().length-1)]; + region = floor.editorVariantRegions()[Mathf.randomSeed(idxWall, 0, floor.editorVariantRegions().length-1)]; mesh.draw(idxWall, region, wx * tilesize, wy * tilesize, 8, 8); } @@ -138,13 +134,15 @@ public class MapRenderer implements Disposable{ if(wall.update || wall.destructible){ mesh.setColor(team.color); - region = Core.atlas.find("block-border"); - }else if(!wall.synthetic() && bw != 0){ - region = wall.icon(Icon.full) == Core.atlas.find("____") ? Core.atlas.find("clear") : wall.icon(Icon.full); + region = Core.atlas.find("block-border-editor"); + }else if(!wall.synthetic() && wall != Blocks.air){ + region = !Core.atlas.isFound(wall.editorIcon()) ? Core.atlas.find("clear-editor") : wall.editorIcon(); offsetX = tilesize/2f - region.getWidth()/2f * Draw.scl; offsetY = tilesize/2f - region.getHeight()/2f * Draw.scl; + }else if(wall == Blocks.air && tile.ore() != null){ + region = tile.ore().editorVariantRegions()[Mathf.randomSeed(idxWall, 0, tile.ore().editorVariantRegions().length-1)];; }else{ - region = Core.atlas.find("clear"); + region = Core.atlas.find("clear-editor"); } mesh.draw(idxDecal, region, diff --git a/core/src/io/anuke/mindustry/editor/MapResizeDialog.java b/core/src/io/anuke/mindustry/editor/MapResizeDialog.java index b0a9ec2cfb..fb6c4f6adb 100644 --- a/core/src/io/anuke/mindustry/editor/MapResizeDialog.java +++ b/core/src/io/anuke/mindustry/editor/MapResizeDialog.java @@ -1,22 +1,20 @@ package io.anuke.mindustry.editor; -import io.anuke.arc.function.BiConsumer; +import io.anuke.arc.function.IntPositionConsumer; import io.anuke.arc.math.Mathf; import io.anuke.arc.scene.ui.layout.Table; -import io.anuke.mindustry.maps.MapTileData; import io.anuke.mindustry.ui.dialogs.FloatingDialog; public class MapResizeDialog extends FloatingDialog{ private static final int minSize = 50, maxSize = 500, increment = 50; int width, height; - public MapResizeDialog(MapEditor editor, BiConsumer cons){ + public MapResizeDialog(MapEditor editor, IntPositionConsumer cons){ super("$editor.resizemap"); shown(() -> { cont.clear(); - MapTileData data = editor.getMap(); - width = data.width(); - height = data.height(); + width = editor.width(); + height = editor.height(); Table table = new Table(); diff --git a/core/src/io/anuke/mindustry/editor/MapSaveDialog.java b/core/src/io/anuke/mindustry/editor/MapSaveDialog.java index 7d00f33d22..bcac2914e9 100644 --- a/core/src/io/anuke/mindustry/editor/MapSaveDialog.java +++ b/core/src/io/anuke/mindustry/editor/MapSaveDialog.java @@ -24,7 +24,7 @@ public class MapSaveDialog extends FloatingDialog{ shown(() -> { cont.clear(); cont.label(() -> { - Map map = world.maps.getByName(field.getText()); + Map map = world.maps.byName(field.getText()); if(map != null){ if(map.custom){ return "$editor.overwrite"; @@ -69,7 +69,7 @@ public class MapSaveDialog extends FloatingDialog{ if(field.getText().isEmpty()){ return true; } - Map map = world.maps.getByName(field.getText()); + Map map = world.maps.byName(field.getText()); return map != null && !map.custom; } } diff --git a/core/src/io/anuke/mindustry/editor/MapView.java b/core/src/io/anuke/mindustry/editor/MapView.java index d382439978..bf115b9f8c 100644 --- a/core/src/io/anuke/mindustry/editor/MapView.java +++ b/core/src/io/anuke/mindustry/editor/MapView.java @@ -18,7 +18,6 @@ import io.anuke.arc.scene.event.Touchable; import io.anuke.arc.scene.ui.TextField; import io.anuke.arc.scene.ui.layout.Unit; import io.anuke.arc.util.Tmp; -import io.anuke.mindustry.editor.DrawOperation.TileOperation; import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.input.Binding; import io.anuke.mindustry.ui.GridImage; @@ -29,8 +28,9 @@ import static io.anuke.mindustry.Vars.ui; public class MapView extends Element implements GestureListener{ private MapEditor editor; private EditorTool tool = EditorTool.pencil; - private OperationStack stack = new OperationStack(); - private DrawOperation op; + //private OperationStack stack = new OperationStack(); + //private DrawOperation op; + //private GridBits used; private Bresenham2 br = new Bresenham2(); private boolean updated = false; private float offsetx, offsety; @@ -87,8 +87,6 @@ public class MapView extends Element implements GestureListener{ mousex = x; mousey = y; - op = new DrawOperation(editor.getMap()); - updated = false; Point2 p = project(x, y); @@ -135,12 +133,7 @@ public class MapView extends Element implements GestureListener{ updated = true; } - if(op != null && updated){ - if(!op.isEmpty()){ - stack.add(op); - } - op = null; - } + editor.flushOp(); if(button == KeyCode.MOUSE_MIDDLE && lastTool != null){ tool = lastTool; @@ -190,14 +183,6 @@ public class MapView extends Element implements GestureListener{ this.tool = tool; } - public void clearStack(){ - stack.clear(); - } - - public OperationStack getStack(){ - return stack; - } - public boolean isGrid(){ return grid; } @@ -206,26 +191,6 @@ public class MapView extends Element implements GestureListener{ this.grid = grid; } - public void undo(){ - if(stack.canUndo()){ - stack.undo(editor); - } - } - - public void redo(){ - if(stack.canRedo()){ - stack.redo(editor); - } - } - - public void addTileOp(TileOperation t){ - op.addOperation(t); - } - - public boolean checkForDuplicates(short x, short y){ - return op.checkDuplicate(x, y); - } - @Override public void act(float delta){ super.act(delta); @@ -259,14 +224,14 @@ public class MapView extends Element implements GestureListener{ } private Point2 project(float x, float y){ - float ratio = 1f / ((float) editor.getMap().width() / editor.getMap().height()); + float ratio = 1f / ((float) editor.width() / editor.height()); float size = Math.min(width, height); float sclwidth = size * zoom; float sclheight = size * zoom * ratio; - x = (x - getWidth() / 2 + sclwidth / 2 - offsetx * zoom) / sclwidth * editor.getMap().width(); - y = (y - getHeight() / 2 + sclheight / 2 - offsety * zoom) / sclheight * editor.getMap().height(); + x = (x - getWidth() / 2 + sclwidth / 2 - offsetx * zoom) / sclwidth * editor.width(); + y = (y - getHeight() / 2 + sclheight / 2 - offsety * zoom) / sclheight * editor.height(); - if(editor.getDrawBlock().size % 2 == 0 && tool != EditorTool.eraser){ + if(editor.drawBlock.size % 2 == 0 && tool != EditorTool.eraser){ return Tmp.g1.set((int) (x - 0.5f), (int) (y - 0.5f)); }else{ return Tmp.g1.set((int) x, (int) y); @@ -274,26 +239,26 @@ public class MapView extends Element implements GestureListener{ } private Vector2 unproject(int x, int y){ - float ratio = 1f / ((float) editor.getMap().width() / editor.getMap().height()); + float ratio = 1f / ((float) editor.width() / editor.height()); float size = Math.min(width, height); float sclwidth = size * zoom; float sclheight = size * zoom * ratio; - float px = ((float) x / editor.getMap().width()) * sclwidth + offsetx * zoom - sclwidth / 2 + getWidth() / 2; - float py = ((float) (y) / editor.getMap().height()) * sclheight + float px = ((float) x / editor.width()) * sclwidth + offsetx * zoom - sclwidth / 2 + getWidth() / 2; + float py = ((float) (y) / editor.height()) * sclheight + offsety * zoom - sclheight / 2 + getHeight() / 2; return vec.set(px, py); } @Override public void draw(){ - float ratio = 1f / ((float) editor.getMap().width() / editor.getMap().height()); + float ratio = 1f / ((float) editor.width() / editor.height()); float size = Math.min(width, height); float sclwidth = size * zoom; float sclheight = size * zoom * ratio; float centerx = x + width / 2 + offsetx * zoom; float centery = y + height / 2 + offsety * zoom; - image.setImageSize(editor.getMap().width(), editor.getMap().height()); + image.setImageSize(editor.width(), editor.height()); if(!ScissorStack.pushScissors(rect.set(x, y, width, height))){ return; @@ -318,18 +283,18 @@ public class MapView extends Element implements GestureListener{ int index = 0; for(int i = 0; i < MapEditor.brushSizes.length; i++){ - if(editor.getBrushSize() == MapEditor.brushSizes[i]){ + if(editor.brushSize == MapEditor.brushSizes[i]){ index = i; break; } } - float scaling = zoom * Math.min(width, height) / editor.getMap().width(); + float scaling = zoom * Math.min(width, height) / editor.width(); Draw.color(Pal.accent); Lines.stroke(Unit.dp.scl(2f)); - if((!editor.getDrawBlock().isMultiblock() || tool == EditorTool.eraser) && tool != EditorTool.fill){ + if((!editor.drawBlock.isMultiblock() || tool == EditorTool.eraser) && tool != EditorTool.fill){ if(tool == EditorTool.line && drawing){ Vector2 v1 = unproject(startx, starty).add(x, y); float sx = v1.x, sy = v1.y; @@ -348,11 +313,11 @@ public class MapView extends Element implements GestureListener{ if((tool.edit || tool == EditorTool.line) && (!mobile || drawing)){ Point2 p = project(mousex, mousey); Vector2 v = unproject(p.x, p.y).add(x, y); - float offset = (editor.getDrawBlock().size % 2 == 0 ? scaling / 2f : 0f); + float offset = (editor.drawBlock.size % 2 == 0 ? scaling / 2f : 0f); Lines.square( v.x + scaling / 2f + offset, v.y + scaling / 2f + offset, - scaling * editor.getDrawBlock().size / 2f); + scaling * editor.drawBlock.size / 2f); } } diff --git a/core/src/io/anuke/mindustry/editor/WaveInfoDialog.java b/core/src/io/anuke/mindustry/editor/WaveInfoDialog.java new file mode 100644 index 0000000000..1cb2fadae4 --- /dev/null +++ b/core/src/io/anuke/mindustry/editor/WaveInfoDialog.java @@ -0,0 +1,236 @@ +package io.anuke.mindustry.editor; + +import io.anuke.arc.Core; +import io.anuke.arc.collection.Array; +import io.anuke.arc.graphics.Color; +import io.anuke.arc.math.Mathf; +import io.anuke.arc.scene.ui.TextField.TextFieldFilter; +import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.arc.util.Align; +import io.anuke.arc.util.Strings; +import io.anuke.arc.util.Time; +import io.anuke.mindustry.Vars; +import io.anuke.mindustry.content.StatusEffects; +import io.anuke.mindustry.content.UnitTypes; +import io.anuke.mindustry.game.DefaultWaves; +import io.anuke.mindustry.game.SpawnGroup; +import io.anuke.mindustry.graphics.Pal; +import io.anuke.mindustry.type.ContentType; +import io.anuke.mindustry.type.UnitType; +import io.anuke.mindustry.ui.dialogs.FloatingDialog; + +import static io.anuke.mindustry.Vars.*; +import static io.anuke.mindustry.game.SpawnGroup.never; + +public class WaveInfoDialog extends FloatingDialog{ + private final MapEditor editor; + private final static int displayed = 20; + private Array groups; + + private Table table, preview; + private int start = 0; + private UnitType lastType = UnitTypes.dagger; + private float updateTimer, updatePeriod = 1f; + + public WaveInfoDialog(MapEditor editor){ + super("$waves.title"); + this.editor = editor; + + shown(this::setup); + hidden(() -> editor.getTags().put("waves", world.maps.writeWaves(groups))); + + addCloseButton(); + buttons.addButton("$settings.reset", () -> ui.showConfirm("$confirm", "$settings.clear.confirm", () ->{ + groups = null; + buildGroups(); + })).size(270f, 64f); + } + + void setup(){ + groups = world.maps.readWaves(editor.getTags().get("waves")); + + cont.clear(); + + cont.table("clear", main -> { + main.pane(t -> table = t).growX().growY().get().setScrollingDisabled(true, false); + main.row(); + main.addButton("$add", () -> { + if(groups == null) groups = new Array<>(); + groups.add(new SpawnGroup(lastType)); + buildGroups(); + }).growX().height(70f); + }).width(390f).growY(); + cont.table("clear", m -> { + m.add("Preview").color(Color.LIGHT_GRAY).growX().center().get().setAlignment(Align.center, Align.center); + m.row(); + m.addButton("-", () -> {}).update(t -> { + if(t.getClickListener().isPressed()){ + updateTimer += Time.delta(); + if(updateTimer >= updatePeriod){ + start = Math.max(start - 1, 0); + updateTimer = 0f; + updateWaves(); + } + } + }).growX().height(70f); + m.row(); + m.pane(t -> preview = t).grow().get().setScrollingDisabled(true, false); + m.row(); + m.addButton("+", () -> {}).update(t -> { + if(t.getClickListener().isPressed()){ + updateTimer += Time.delta(); + if(updateTimer >= updatePeriod){ + start ++; + updateTimer = 0f; + updateWaves(); + } + } + }).growX().height(70f); + }).growY().width(180f).growY(); + + buildGroups(); + } + + void buildGroups(){ + table.clear(); + table.top(); + table.margin(10f); + + if(groups != null){ + for(SpawnGroup group : groups){ + table.table("clear", t -> { + t.margin(6f).defaults().pad(2).padLeft(5f).growX().left(); + t.addButton(b -> { + b.left(); + b.addImage(group.type.iconRegion).size(30f).padRight(3); + b.add(group.type.localizedName).color(Pal.accent); + }, () -> showUpdate(group)).pad(-6f).padBottom(0f); + + t.row(); + t.table(spawns -> { + spawns.addField("" + group.begin, TextFieldFilter.digitsOnly, text -> { + if(Strings.canParsePostiveInt(text)){ + group.begin = Strings.parseInt(text); + updateWaves(); + } + }).width(100f); + spawns.add("$waves.to").padLeft(4).padRight(4); + spawns.addField(group.end == never ? "" : group.end + "", TextFieldFilter.digitsOnly, text -> { + if(Strings.canParsePostiveInt(text)){ + group.end = Strings.parseInt(text); + updateWaves(); + }else if(text.isEmpty()){ + group.end = never; + updateWaves(); + } + }).width(100f).get().setMessageText(Core.bundle.get("waves.never")); + }); + t.row(); + t.table(p -> { + p.add("$waves.every").padRight(4); + p.addField(group.spacing + "", TextFieldFilter.digitsOnly, text -> { + if(Strings.canParsePostiveInt(text)){ + group.spacing = Strings.parseInt(text); + updateWaves(); + } + }).width(100f); + p.add("$waves.waves").padLeft(4); + }); + + t.row(); + t.table(a -> { + a.addField(group.unitAmount + "", TextFieldFilter.digitsOnly, text -> { + if(Strings.canParsePostiveInt(text)){ + group.unitAmount = Strings.parseInt(text); + updateWaves(); + } + }).width(80f); + + a.add(" + "); + a.addField(Strings.toFixed(Math.max((Mathf.isZero(group.unitScaling) ? 0 : 1f/group.unitScaling), 0), 2), TextFieldFilter.floatsOnly, text -> { + if(Strings.canParsePositiveFloat(text)){ + group.unitScaling = 1f / Strings.parseFloat(text); + updateWaves(); + } + }).width(80f); + a.add("$waves.perspawn").padLeft(4); + }); + + t.row(); + t.addCheck("$waves.boss", b -> group.effect = (b ? StatusEffects.boss : null)).padTop(4).update(b -> b.setChecked(group.effect == StatusEffects.boss)); + + t.row(); + t.addButton("$waves.remove", () -> { + groups.remove(group); + table.getCell(t).pad(0f); + t.remove(); + updateWaves(); + }).growX().pad(-6f).padTop(5); + }).width(340f).pad(5); + table.row(); + } + }else{ + table.add("$editor.default"); + } + + updateWaves(); + } + + void showUpdate(SpawnGroup group){ + FloatingDialog dialog = new FloatingDialog(""); + dialog.setFillParent(false); + int i = 0; + for(UnitType type : content.units()){ + dialog.cont.addButton(t -> { + t.left(); + t.addImage(type.iconRegion).size(40f).padRight(2f); + t.add(type.localizedName); + }, () -> { + lastType = type; + group.type = type; + dialog.hide(); + buildGroups(); + }).pad(2).margin(12f).fillX(); + if(++i % 2 == 0)dialog.cont.row(); + } + dialog.show(); + } + + void updateWaves(){ + preview.clear(); + preview.top(); + + Array groups = (this.groups == null ? DefaultWaves.get() : this.groups); + + for(int i = start; i < displayed + start; i ++){ + int wave = i; + preview.table("underline", table -> { + table.add(wave + "").color(Pal.accent).center().colspan(2).get().setAlignment(Align.center, Align.center); + table.row(); + + int[] spawned = new int[Vars.content.getBy(ContentType.unit).size]; + + for(SpawnGroup spawn : groups){ + spawned[spawn.type.id] += spawn.getUnitsSpawned(wave); + } + + int f = 0; + + for(int j = 0; j < spawned.length; j++){ + if(spawned[j] > 0){ + UnitType type = content.getByID(ContentType.unit, j); + table.addImage(type.iconRegion).size(30f).padRight(4); + table.add(spawned[j] + "x").color(Color.LIGHT_GRAY).padRight(6); + table.row(); + } + } + + if(table.getChildren().size == 1){ + table.add("$none").color(Pal.remove); + } + }).width(110f).pad(2f); + + preview.row(); + } + } +} diff --git a/core/src/io/anuke/mindustry/editor/generation/DistortFilter.java b/core/src/io/anuke/mindustry/editor/generation/DistortFilter.java new file mode 100644 index 0000000000..042d08ed01 --- /dev/null +++ b/core/src/io/anuke/mindustry/editor/generation/DistortFilter.java @@ -0,0 +1,25 @@ +package io.anuke.mindustry.editor.generation; + +import io.anuke.mindustry.editor.MapGenerateDialog.DummyTile; +import io.anuke.mindustry.editor.generation.FilterOption.SliderOption; +import io.anuke.mindustry.world.blocks.Floor; + +public class DistortFilter extends GenerateFilter{ + float scl = 40, mag = 5; + + { + options( + new SliderOption("scale", () -> scl, f -> scl = f, 1f, 400f), + new SliderOption("mag", () -> mag, f -> mag = f, 0.5f, 100f) + ); + } + + @Override + public void apply(){ + DummyTile 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); + + in.floor = tile.floor; + if(!tile.block.synthetic() && !in.block.synthetic()) in.block = tile.block; + if(!((Floor)in.floor).isLiquid) in.ore = tile.ore; + } +} diff --git a/core/src/io/anuke/mindustry/editor/generation/FilterOption.java b/core/src/io/anuke/mindustry/editor/generation/FilterOption.java new file mode 100644 index 0000000000..f3e7d3fbee --- /dev/null +++ b/core/src/io/anuke/mindustry/editor/generation/FilterOption.java @@ -0,0 +1,83 @@ +package io.anuke.mindustry.editor.generation; + +import io.anuke.arc.Core; +import io.anuke.arc.function.*; +import io.anuke.arc.scene.style.TextureRegionDrawable; +import io.anuke.arc.scene.ui.Slider; +import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.mindustry.Vars; +import io.anuke.mindustry.ui.dialogs.FloatingDialog; +import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.Block.Icon; +import io.anuke.mindustry.world.blocks.Floor; +import io.anuke.mindustry.world.blocks.OreBlock; + +public abstract class FilterOption{ + public static final Predicate floorsOnly = b -> (b instanceof Floor && !(b instanceof OreBlock)) && Core.atlas.isFound(b.icon(Icon.full)); + public static final Predicate wallsOnly = b -> (!b.synthetic() && !(b instanceof Floor)) && Core.atlas.isFound(b.icon(Icon.full)); + public static final Predicate oresOnly = b -> b instanceof OreBlock && Core.atlas.isFound(b.icon(Icon.full)); + + public abstract void build(Table table); + public Runnable changed = () -> {}; + + static class SliderOption extends FilterOption{ + final String name; + final FloatProvider getter; + final FloatConsumer setter; + final float min, max; + + SliderOption(String name, FloatProvider getter, FloatConsumer setter, float min, float max){ + this.name = name; + this.getter = getter; + this.setter = setter; + this.min = min; + this.max = max; + } + + @Override + public void build(Table table){ + table.add("$filter.option." + name); + table.row(); + Slider slider = table.addSlider(min, max, (max-min)/200f, setter).growX().get(); + slider.setValue(getter.get()); + slider.changed(changed); + } + } + + static class BlockOption extends FilterOption{ + final String name; + final Supplier supplier; + final Consumer consumer; + final Predicate filter; + + BlockOption(String name, Supplier supplier, Consumer consumer, Predicate filter){ + this.name = name; + this.supplier = supplier; + this.consumer = consumer; + this.filter = filter; + } + + @Override + public void build(Table table){ + table.addButton(b -> b.addImage(supplier.get().icon(Icon.small)).update(i -> ((TextureRegionDrawable)i.getDrawable()).setRegion(supplier.get().icon(Icon.small))).size(8*3), () -> { + FloatingDialog dialog = new FloatingDialog(""); + dialog.setFillParent(false); + int i = 0; + for(Block block : Vars.content.blocks()){ + if(!filter.test(block)) continue; + + dialog.cont.addImage(block.icon(Icon.medium)).size(8*4).pad(3).get().clicked(() -> { + consumer.accept(block); + dialog.hide(); + changed.run(); + }); + if(++i % 10 == 0) dialog.cont.row(); + } + + dialog.show(); + }).pad(4).margin(12f); + + table.add("$filter.option." + name); + } + } +} diff --git a/core/src/io/anuke/mindustry/editor/generation/GenerateFilter.java b/core/src/io/anuke/mindustry/editor/generation/GenerateFilter.java new file mode 100644 index 0000000000..d889907b0c --- /dev/null +++ b/core/src/io/anuke/mindustry/editor/generation/GenerateFilter.java @@ -0,0 +1,91 @@ +package io.anuke.mindustry.editor.generation; + +import io.anuke.arc.Core; +import io.anuke.arc.math.Mathf; +import io.anuke.arc.util.Pack; +import io.anuke.arc.util.noise.RidgedPerlin; +import io.anuke.arc.util.noise.Simplex; +import io.anuke.mindustry.editor.MapEditor; +import io.anuke.mindustry.editor.MapGenerateDialog.DummyTile; +import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.blocks.Floor; + +public abstract class GenerateFilter{ + protected float o = (float)(Math.random()*10000000.0); + protected long seed; + protected GenerateInput in; + + public FilterOption[] options; + + protected abstract void apply(); + + 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; + } + + 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 rnoise(float x, float y, float scl, float mag){ + return in.pnoise.getValue((int)(x + o), (int)(y + o), 1f/scl)*mag; + } + + public void randomize(){ + seed = Mathf.random(99999999); + } + + protected float chance(){ + return Mathf.randomSeed(Pack.longInt(in.x, in.y + (int)o)); + } + + public void options(FilterOption... options){ + this.options = options; + } + + public String name(){ + return Core.bundle.get("filter." + getClass().getSimpleName().toLowerCase().replace("filter", ""), getClass().getSimpleName().replace("Filter", "")); + } + + public final void apply(GenerateInput in){ + this.in = in; + apply(); + } + + public static class GenerateInput{ + public Floor srcfloor; + public Block srcblock; + public Block srcore; + public int x, y; + + public MapEditor editor; + public Block floor, block, ore; + + Simplex noise = new Simplex(); + RidgedPerlin pnoise = new RidgedPerlin(0, 1); + TileProvider buffer; + + public void begin(MapEditor editor, int x, int y, Block floor, Block block, Block ore){ + this.editor = editor; + this.floor = this.srcfloor = (Floor)floor; + this.block = this.srcblock = block; + this.ore = srcore = ore; + this.x = x; + this.y = y; + } + + public void setFilter(GenerateFilter filter, TileProvider buffer){ + this.buffer = buffer; + noise.setSeed(filter.seed); + pnoise.setSeed((int)(filter.seed + 1)); + } + + DummyTile tile(float x, float y){ + return buffer.get(Mathf.clamp((int)x, 0, editor.width() - 1), Mathf.clamp((int)y, 0, editor.height() - 1)); + } + + public interface TileProvider{ + DummyTile get(int x, int y); + } + } +} diff --git a/core/src/io/anuke/mindustry/editor/generation/NoiseFilter.java b/core/src/io/anuke/mindustry/editor/generation/NoiseFilter.java new file mode 100644 index 0000000000..580c6331a2 --- /dev/null +++ b/core/src/io/anuke/mindustry/editor/generation/NoiseFilter.java @@ -0,0 +1,35 @@ +package io.anuke.mindustry.editor.generation; + +import io.anuke.mindustry.content.Blocks; +import io.anuke.mindustry.editor.generation.FilterOption.BlockOption; +import io.anuke.mindustry.editor.generation.FilterOption.SliderOption; +import io.anuke.mindustry.world.Block; + +import static io.anuke.mindustry.editor.generation.FilterOption.floorsOnly; +import static io.anuke.mindustry.editor.generation.FilterOption.wallsOnly; + +public class NoiseFilter extends GenerateFilter{ + float scl = 40, threshold = 0.5f, octaves = 3f, falloff = 0.5f; + Block floor = Blocks.stone, block = Blocks.rocks; + + { + options( + 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("floor", () -> floor, b -> floor = b, floorsOnly), + new BlockOption("wall", () -> block, b -> block = b, wallsOnly) + ); + } + + @Override + public void apply(){ + float noise = noise(in.x, in.y, scl, 1f, octaves, falloff); + + if(noise > threshold){ + in.floor = floor; + if(wallsOnly.test(in.srcblock)) in.block = block; + } + } +} diff --git a/core/src/io/anuke/mindustry/editor/generation/OreFilter.java b/core/src/io/anuke/mindustry/editor/generation/OreFilter.java new file mode 100644 index 0000000000..976878f958 --- /dev/null +++ b/core/src/io/anuke/mindustry/editor/generation/OreFilter.java @@ -0,0 +1,32 @@ +package io.anuke.mindustry.editor.generation; + +import io.anuke.mindustry.content.Blocks; +import io.anuke.mindustry.editor.generation.FilterOption.BlockOption; +import io.anuke.mindustry.editor.generation.FilterOption.SliderOption; +import io.anuke.mindustry.world.Block; + +import static io.anuke.mindustry.editor.generation.FilterOption.*; + +public class OreFilter extends GenerateFilter{ + float scl = 40, threshold = 0.8f, octaves = 3f, falloff = 0.5f; + Block ore = Blocks.oreCopper; + + { + options( + 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) + ); + } + + @Override + public void apply(){ + float noise = noise(in.x, in.y, scl, 1f, octaves, falloff); + + if(noise > threshold && !in.srcfloor.isLiquid){ + in.ore = ore; + } + } +} diff --git a/core/src/io/anuke/mindustry/editor/generation/RiverNoiseFilter.java b/core/src/io/anuke/mindustry/editor/generation/RiverNoiseFilter.java new file mode 100644 index 0000000000..2920ee7ad3 --- /dev/null +++ b/core/src/io/anuke/mindustry/editor/generation/RiverNoiseFilter.java @@ -0,0 +1,36 @@ +package io.anuke.mindustry.editor.generation; + +import io.anuke.mindustry.content.Blocks; +import io.anuke.mindustry.editor.generation.FilterOption.BlockOption; +import io.anuke.mindustry.editor.generation.FilterOption.SliderOption; +import io.anuke.mindustry.world.Block; + +import static io.anuke.mindustry.editor.generation.FilterOption.floorsOnly; + +public class RiverNoiseFilter extends GenerateFilter{ + float scl = 40, threshold = 0f, threshold2 = 0.1f; + Block floor = Blocks.water, floor2 = Blocks.deepwater; + + { + options( + new SliderOption("scale", () -> scl, f -> scl = f, 1f, 500f), + new SliderOption("threshold", () -> threshold, f -> threshold = f, 0f, 1f), + new SliderOption("threshold2", () -> threshold2, f -> threshold2 = f, 0f, 1f), + new BlockOption("floor", () -> floor, b -> floor = b, floorsOnly), + new BlockOption("floor2", () -> floor2, b -> floor2 = b, floorsOnly) + ); + } + + @Override + public void apply(){ + float noise = rnoise(in.x, in.y, scl, 1f); + + if(noise >= threshold){ + in.floor = floor; + + if(noise >= threshold2){ + in.floor = floor2; + } + } + } +} diff --git a/core/src/io/anuke/mindustry/editor/generation/ScatterFilter.java b/core/src/io/anuke/mindustry/editor/generation/ScatterFilter.java new file mode 100644 index 0000000000..af6b09822e --- /dev/null +++ b/core/src/io/anuke/mindustry/editor/generation/ScatterFilter.java @@ -0,0 +1,30 @@ +package io.anuke.mindustry.editor.generation; + +import io.anuke.mindustry.content.Blocks; +import io.anuke.mindustry.editor.generation.FilterOption.BlockOption; +import io.anuke.mindustry.editor.generation.FilterOption.SliderOption; +import io.anuke.mindustry.world.Block; + +import static io.anuke.mindustry.editor.generation.FilterOption.floorsOnly; +import static io.anuke.mindustry.editor.generation.FilterOption.wallsOnly; + +public class ScatterFilter extends GenerateFilter{ + float chance = 0.1f; + Block floor = Blocks.ice, block = Blocks.icerocks; + + { + options( + new SliderOption("chance", () -> chance, f -> chance = f, 0f, 1f), + new BlockOption("floor", () -> floor, b -> floor = b, floorsOnly), + new BlockOption("block", () -> block, b -> block = b, wallsOnly) + ); + } + + @Override + public void apply(){ + + if(in.srcfloor == floor && in.srcblock == Blocks.air && chance() <= chance){ + in.block = block; + } + } +} diff --git a/core/src/io/anuke/mindustry/editor/generation/TerrainFilter.java b/core/src/io/anuke/mindustry/editor/generation/TerrainFilter.java new file mode 100644 index 0000000000..e0bf3234f3 --- /dev/null +++ b/core/src/io/anuke/mindustry/editor/generation/TerrainFilter.java @@ -0,0 +1,42 @@ +package io.anuke.mindustry.editor.generation; + +import io.anuke.arc.math.Mathf; +import io.anuke.mindustry.content.Blocks; +import io.anuke.mindustry.editor.generation.FilterOption.BlockOption; +import io.anuke.mindustry.editor.generation.FilterOption.SliderOption; +import io.anuke.mindustry.world.Block; + +import static io.anuke.mindustry.editor.generation.FilterOption.floorsOnly; +import static io.anuke.mindustry.editor.generation.FilterOption.wallsOnly; + +public class TerrainFilter extends GenerateFilter{ + float scl = 40, threshold = 0.9f, octaves = 3f, falloff = 0.5f, magnitude = 1f, circleScl = 2.1f; + Block floor = Blocks.stone, block = Blocks.rocks; + + { + options( + 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, floorsOnly), + new BlockOption("wall", () -> block, b -> block = b, wallsOnly) + ); + } + + @Override + public void apply(){ + float noise = noise(in.x, in.y, scl, magnitude, octaves, falloff) + Mathf.dst((float) in.x / in.editor.width(), (float) in.y / in.editor.height(), 0.5f, 0.5f) * circleScl; + + in.floor = floor; + in.ore = Blocks.air; + + if(noise >= threshold){ + in.block = block; + }else{ + in.block = Blocks.air; + } + } +} \ No newline at end of file diff --git a/core/src/io/anuke/mindustry/entities/Predict.java b/core/src/io/anuke/mindustry/entities/Predict.java index d4a935c173..71b95ee7f2 100644 --- a/core/src/io/anuke/mindustry/entities/Predict.java +++ b/core/src/io/anuke/mindustry/entities/Predict.java @@ -2,6 +2,7 @@ package io.anuke.mindustry.entities; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Vector2; +import io.anuke.arc.util.Time; import io.anuke.mindustry.entities.traits.TargetTrait; /** @@ -24,6 +25,8 @@ public class Predict{ * @return the intercept location */ public static Vector2 intercept(float srcx, float srcy, float dstx, float dsty, float dstvx, float dstvy, float v){ + dstvx /= Time.delta(); + dstvy /= Time.delta(); float tx = dstx - srcx, ty = dsty - srcy; diff --git a/core/src/io/anuke/mindustry/entities/bullet/Bullet.java b/core/src/io/anuke/mindustry/entities/bullet/Bullet.java index 9206c8d6c3..ae61553586 100644 --- a/core/src/io/anuke/mindustry/entities/bullet/Bullet.java +++ b/core/src/io/anuke/mindustry/entities/bullet/Bullet.java @@ -2,8 +2,6 @@ package io.anuke.mindustry.entities.bullet; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; -import io.anuke.mindustry.entities.EntityGroup; -import io.anuke.mindustry.entities.impl.SolidEntity; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Rectangle; import io.anuke.arc.math.geom.Vector2; @@ -12,9 +10,11 @@ import io.anuke.arc.util.Time; import io.anuke.arc.util.Tmp; import io.anuke.arc.util.pooling.Pool.Poolable; import io.anuke.arc.util.pooling.Pools; +import io.anuke.mindustry.entities.EntityGroup; +import io.anuke.mindustry.entities.effect.Lightning; +import io.anuke.mindustry.entities.impl.SolidEntity; import io.anuke.mindustry.entities.traits.*; import io.anuke.mindustry.entities.type.Unit; -import io.anuke.mindustry.entities.effect.Lightning; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.world.Tile; @@ -86,11 +86,17 @@ public class Bullet extends SolidEntity implements DamageTrait, ScaleTrait, Pool } /**Internal use only.*/ - @Remote(called = Loc.server) + @Remote(called = Loc.server, unreliable = true) public static void createBullet(BulletType type, float x, float y, float angle){ create(type, null, Team.none, x, y, angle); } + /**ok*/ + @Remote(called = Loc.server, unreliable = true) + public static void createBullet(BulletType type, Team team, float x, float y, float angle){ + create(type, null, team, x, y, angle); + } + public Entity getOwner(){ return owner; } diff --git a/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java b/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java index 047a9d0dd5..39bec65fce 100644 --- a/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java +++ b/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java @@ -252,10 +252,10 @@ public interface BuilderTrait extends Entity, TeamTrait{ TileEntity core = unit.getClosestCore(); if(core == null || tile.block() != Blocks.air || dst(tile.worldx(), tile.worldy()) > mineDistance - || tile.floor().itemDrop == null || !unit.acceptsItem(tile.floor().itemDrop) || !canMine(tile.floor().itemDrop)){ + || tile.drop() == null || !unit.acceptsItem(tile.drop()) || !canMine(tile.drop())){ setMineTile(null); }else{ - Item item = tile.floor().itemDrop; + Item item = tile.drop(); unit.rotation = Mathf.slerpDelta(unit.rotation, unit.angleTo(tile.worldx(), tile.worldy()), 0.4f); if(Mathf.chance(Time.delta() * (0.06 - item.hardness * 0.01) * getMinePower())){ diff --git a/core/src/io/anuke/mindustry/entities/type/BaseUnit.java b/core/src/io/anuke/mindustry/entities/type/BaseUnit.java index 7d62c05d16..2542e79bdd 100644 --- a/core/src/io/anuke/mindustry/entities/type/BaseUnit.java +++ b/core/src/io/anuke/mindustry/entities/type/BaseUnit.java @@ -241,10 +241,14 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ return; } + if(!isFlying() && (world.tileWorld(x, y) != null && world.tileWorld(x, y).solid())){ + kill(); + } + avoidOthers(1.25f); if(spawner != noSpawner && (world.tile(spawner) == null || world.tile(spawner).entity == null)){ - damage(health); + kill(); } updateTargeting(); @@ -337,6 +341,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ public void write(DataOutput data) throws IOException{ super.writeSave(data); data.writeByte(type.id); + data.writeInt(spawner); } @Override @@ -344,6 +349,7 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ float lastx = x, lasty = y, lastrot = rotation; super.readSave(data); this.type = content.getByID(ContentType.unit, data.readByte()); + this.spawner = data.readInt(); interpolator.read(lastx, lasty, x, y, rotation); rotation = lastrot; diff --git a/core/src/io/anuke/mindustry/entities/type/GroundUnit.java b/core/src/io/anuke/mindustry/entities/type/GroundUnit.java index 985f551bc6..2982057316 100644 --- a/core/src/io/anuke/mindustry/entities/type/GroundUnit.java +++ b/core/src/io/anuke/mindustry/entities/type/GroundUnit.java @@ -178,9 +178,9 @@ public abstract class GroundUnit extends BaseUnit{ } protected void patrol(){ - vec.trns(baseRotation, type.speed * Time.delta() * 2); + vec.trns(baseRotation, type.speed * Time.delta()); velocity.add(vec.x, vec.y); - vec.trns(baseRotation, type.hitsizeTile); + vec.trns(baseRotation, type.hitsizeTile * 3); Tile tile = world.tileWorld(x + vec.x, y + vec.y); if((tile == null || tile.solid() || tile.floor().drownTime > 0) || stuckTime > 10f){ baseRotation += Mathf.sign(id % 2 - 0.5f) * Time.delta() * 3f; diff --git a/core/src/io/anuke/mindustry/entities/type/Player.java b/core/src/io/anuke/mindustry/entities/type/Player.java index dfd5e02029..a592a0ce85 100644 --- a/core/src/io/anuke/mindustry/entities/type/Player.java +++ b/core/src/io/anuke/mindustry/entities/type/Player.java @@ -797,6 +797,7 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ if(isLocal){ stream.writeByte(mech.id); stream.writeByte(playerIndex); + stream.writeInt(lastSpawner == null ? noSpawner : lastSpawner.getTile().pos()); super.writeSave(stream, false); } } @@ -808,12 +809,17 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ if(local && !headless){ byte mechid = stream.readByte(); int index = stream.readByte(); + int spawner = stream.readInt(); + if(world.tile(spawner) != null && world.tile(spawner).entity != null && world.tile(spawner).entity instanceof SpawnerTrait){ + lastSpawner = (SpawnerTrait)(world.tile(spawner).entity); + } players[index].readSaveSuper(stream); players[index].mech = content.getByID(ContentType.mech, mechid); players[index].dead = false; }else if(local){ byte mechid = stream.readByte(); stream.readByte(); + stream.readInt(); readSaveSuper(stream); mech = content.getByID(ContentType.mech, mechid); dead = false; @@ -833,7 +839,7 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ buffer.writeByte(Pack.byteValue(isAdmin) | (Pack.byteValue(dead) << 1) | (Pack.byteValue(isBoosting) << 2)); buffer.writeInt(Color.rgba8888(color)); buffer.writeByte(mech.id); - buffer.writeInt(mining == null ? -1 : mining.pos()); + buffer.writeInt(mining == null ? noSpawner : mining.pos()); buffer.writeInt(spawner == null ? noSpawner : spawner.getTile().pos()); buffer.writeShort((short) (baseRotation * 2)); diff --git a/core/src/io/anuke/mindustry/entities/type/TileEntity.java b/core/src/io/anuke/mindustry/entities/type/TileEntity.java index fee8f4ac00..fa302ada5f 100644 --- a/core/src/io/anuke/mindustry/entities/type/TileEntity.java +++ b/core/src/io/anuke/mindustry/entities/type/TileEntity.java @@ -59,7 +59,7 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{ private boolean sleeping; private float sleepTime; - @Remote(called = Loc.server) + @Remote(called = Loc.server, unreliable = true) public static void onTileDamage(Tile tile, float health){ if(tile.entity != null){ tile.entity.health = health; @@ -269,7 +269,6 @@ public class TileEntity extends BaseEntity implements TargetTrait, HealthTrait{ //TODO better smoke effect, this one is awful if(health != 0 && health < tile.block().health && !(tile.block() instanceof Wall) && Mathf.chance(0.009f * Time.delta() * (1f - health / tile.block().health))){ - Effects.effect(Fx.smoke, x + Mathf.range(4), y + Mathf.range(4)); } diff --git a/core/src/io/anuke/mindustry/game/DefaultWaves.java b/core/src/io/anuke/mindustry/game/DefaultWaves.java index dda11e2c48..8880c2996d 100644 --- a/core/src/io/anuke/mindustry/game/DefaultWaves.java +++ b/core/src/io/anuke/mindustry/game/DefaultWaves.java @@ -9,159 +9,158 @@ import io.anuke.mindustry.type.ItemStack; public class DefaultWaves{ private static Array spawns; - public static Array getDefaultSpawns(){ + public static Array get(){ if(spawns == null && UnitTypes.dagger != null){ spawns = Array.with( - new SpawnGroup(UnitTypes.dagger){{ - end = 8; - unitScaling = 2; - }}, + new SpawnGroup(UnitTypes.dagger){{ + end = 8; + unitScaling = 2; + }}, - new SpawnGroup(UnitTypes.wraith){{ - begin = 12; - end = 14; - unitScaling = 2; - }}, + new SpawnGroup(UnitTypes.wraith){{ + begin = 12; + end = 14; + unitScaling = 2; + }}, - new SpawnGroup(UnitTypes.dagger){{ - begin = 11; - unitScaling = 2; - spacing = 2; - max = 4; - }}, + new SpawnGroup(UnitTypes.dagger){{ + begin = 11; + unitScaling = 2; + spacing = 2; + max = 4; + }}, - new SpawnGroup(UnitTypes.titan){{ - begin = 9; - spacing = 3; - unitScaling = 2; + new SpawnGroup(UnitTypes.titan){{ + begin = 9; + spacing = 3; + unitScaling = 2; - end = 30; - }}, + end = 30; + }}, - new SpawnGroup(UnitTypes.dagger){{ - begin = 10; - unitScaling = 2; - unitAmount = 1; - spacing = 2; - end = 30; - }}, + new SpawnGroup(UnitTypes.dagger){{ + begin = 8; + unitScaling = 1; + unitAmount = 1; + spacing = 2; + end = 30; + }}, - new SpawnGroup(UnitTypes.titan){{ - begin = 28; - spacing = 3; - unitScaling = 1; - end = 40; - }}, + new SpawnGroup(UnitTypes.titan){{ + begin = 28; + spacing = 3; + unitScaling = 1; + end = 40; + }}, - new SpawnGroup(UnitTypes.titan){{ - begin = 45; - spacing = 3; - unitScaling = 2; - effect = StatusEffects.overdrive; - }}, + new SpawnGroup(UnitTypes.titan){{ + begin = 45; + spacing = 3; + unitScaling = 2; + effect = StatusEffects.overdrive; + }}, - new SpawnGroup(UnitTypes.titan){{ - begin = 120; - spacing = 2; - unitScaling = 3; - unitAmount = 5; - effect = StatusEffects.overdrive; - }}, + new SpawnGroup(UnitTypes.titan){{ + begin = 120; + spacing = 2; + unitScaling = 3; + unitAmount = 5; + effect = StatusEffects.overdrive; + }}, - new SpawnGroup(UnitTypes.wraith){{ - begin = 16; - unitScaling = 2; - spacing = 2; + new SpawnGroup(UnitTypes.wraith){{ + begin = 16; + unitScaling = 1; + spacing = 2; - end = 39; - max = 7; - }}, + max = 7; + }}, - new SpawnGroup(UnitTypes.dagger){{ - begin = 82; - spacing = 3; - unitAmount = 4; - unitScaling = 3; - effect = StatusEffects.overdrive; - }}, + new SpawnGroup(UnitTypes.dagger){{ + begin = 82; + spacing = 3; + unitAmount = 4; + unitScaling = 3; + effect = StatusEffects.overdrive; + }}, - new SpawnGroup(UnitTypes.dagger){{ - begin = 41; - spacing = 5; - unitAmount = 1; - unitScaling = 3; - effect = StatusEffects.shielded; - max = 10; - }}, + new SpawnGroup(UnitTypes.dagger){{ + begin = 41; + spacing = 5; + unitAmount = 1; + unitScaling = 3; + effect = StatusEffects.shielded; + max = 10; + }}, - new SpawnGroup(UnitTypes.fortress){{ - begin = 40; - spacing = 5; - unitAmount = 2; - unitScaling = 3; - max = 10; - }}, + new SpawnGroup(UnitTypes.fortress){{ + begin = 40; + spacing = 5; + unitAmount = 2; + unitScaling = 3; + max = 10; + }}, - new SpawnGroup(UnitTypes.dagger){{ - begin = 35; - spacing = 3; - unitAmount = 4; - effect = StatusEffects.overdrive; - items = new ItemStack(Items.blastCompound, 60); - end = 60; - }}, + new SpawnGroup(UnitTypes.dagger){{ + begin = 35; + spacing = 3; + unitAmount = 4; + effect = StatusEffects.overdrive; + items = new ItemStack(Items.blastCompound, 60); + end = 60; + }}, - new SpawnGroup(UnitTypes.dagger){{ - begin = 42; - spacing = 3; - unitAmount = 4; - effect = StatusEffects.overdrive; - items = new ItemStack(Items.pyratite, 100); - end = 130; - }}, + new SpawnGroup(UnitTypes.dagger){{ + begin = 42; + spacing = 3; + unitAmount = 4; + effect = StatusEffects.overdrive; + items = new ItemStack(Items.pyratite, 100); + end = 130; + }}, - new SpawnGroup(UnitTypes.ghoul){{ - begin = 40; - unitAmount = 2; - spacing = 2; - unitScaling = 3; - max = 8; - }}, + new SpawnGroup(UnitTypes.ghoul){{ + begin = 40; + unitAmount = 2; + spacing = 2; + unitScaling = 3; + max = 8; + }}, - new SpawnGroup(UnitTypes.wraith){{ - begin = 50; - unitAmount = 4; - unitScaling = 3; - spacing = 5; - effect = StatusEffects.overdrive; - max = 8; - }}, + new SpawnGroup(UnitTypes.wraith){{ + begin = 50; + unitAmount = 4; + unitScaling = 3; + spacing = 5; + effect = StatusEffects.overdrive; + max = 8; + }}, - new SpawnGroup(UnitTypes.revenant){{ - begin = 50; - unitAmount = 2; - unitScaling = 3; - spacing = 5; - max = 8; - }}, + new SpawnGroup(UnitTypes.revenant){{ + begin = 50; + unitAmount = 2; + unitScaling = 3; + spacing = 5; + max = 8; + }}, - new SpawnGroup(UnitTypes.ghoul){{ - begin = 53; - unitAmount = 2; - unitScaling = 3; - spacing = 4; - max = 8; - end = 74; - }}, + new SpawnGroup(UnitTypes.ghoul){{ + begin = 53; + unitAmount = 2; + unitScaling = 3; + spacing = 4; + max = 8; + end = 74; + }}, - new SpawnGroup(UnitTypes.ghoul){{ - begin = 53; - unitAmount = 2; - unitScaling = 3; - spacing = 4; - max = 8; - end = 74; - }} + new SpawnGroup(UnitTypes.ghoul){{ + begin = 53; + unitAmount = 2; + unitScaling = 3; + spacing = 4; + max = 8; + end = 74; + }} ); } return spawns == null ? new Array<>() : spawns; diff --git a/core/src/io/anuke/mindustry/game/RulePreset.java b/core/src/io/anuke/mindustry/game/RulePreset.java index 174f9e0df9..2fb2fbe504 100644 --- a/core/src/io/anuke/mindustry/game/RulePreset.java +++ b/core/src/io/anuke/mindustry/game/RulePreset.java @@ -9,13 +9,13 @@ public enum RulePreset{ waveTimer = true; waves = true; unitDrops = true; - spawns = DefaultWaves.getDefaultSpawns(); + spawns = DefaultWaves.get(); }}), sandbox(() -> new Rules(){{ infiniteResources = true; waves = true; waveTimer = false; - spawns = DefaultWaves.getDefaultSpawns(); + spawns = DefaultWaves.get(); }}), attack(() -> new Rules(){{ enemyCheat = true; diff --git a/core/src/io/anuke/mindustry/game/Rules.java b/core/src/io/anuke/mindustry/game/Rules.java index a23b15321d..cf31cce7e0 100644 --- a/core/src/io/anuke/mindustry/game/Rules.java +++ b/core/src/io/anuke/mindustry/game/Rules.java @@ -28,5 +28,5 @@ public class Rules{ /**Zone ID, -1 for invalid zone.*/ public byte zone = -1; /**Spawn layout. Since only zones modify this, it should be assigned on save load.*/ - public transient Array spawns = DefaultWaves.getDefaultSpawns(); + public transient Array spawns = DefaultWaves.get(); } diff --git a/core/src/io/anuke/mindustry/game/SpawnGroup.java b/core/src/io/anuke/mindustry/game/SpawnGroup.java index 64e399b3db..6847b9a116 100644 --- a/core/src/io/anuke/mindustry/game/SpawnGroup.java +++ b/core/src/io/anuke/mindustry/game/SpawnGroup.java @@ -1,41 +1,51 @@ package io.anuke.mindustry.game; +import io.anuke.arc.util.serialization.Json; +import io.anuke.arc.util.serialization.Json.Serializable; +import io.anuke.arc.util.serialization.JsonValue; import io.anuke.mindustry.entities.type.BaseUnit; +import io.anuke.mindustry.type.ContentType; import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.type.StatusEffect; import io.anuke.mindustry.type.UnitType; +import static io.anuke.mindustry.Vars.content; + /** * A spawn group defines spawn information for a specific type of unit, with optional extra information like * weapon equipped, ammo used, and status effects. * Each spawn group can have multiple sub-groups spawned in different areas of the map. */ -public class SpawnGroup{ - protected static final int never = Integer.MAX_VALUE; +public class SpawnGroup implements Serializable{ + public static final int never = Integer.MAX_VALUE; /**The unit type spawned*/ - public final UnitType type; + public UnitType type; /**When this spawn should end*/ - protected int end = never; + public int end = never; /**When this spawn should start*/ - protected int begin; + public int begin; /**The spacing, in waves, of spawns. For example, 2 = spawns every other wave*/ - protected int spacing = 1; + public int spacing = 1; /**Maximum amount of units that spawn*/ - protected int max = 40; + public int max = 40; /**How many waves need to pass before the amount of units spawned increases by 1*/ - protected float unitScaling = 9999f; + public float unitScaling = never; /**Amount of enemies spawned initially, with no scaling*/ - protected int unitAmount = 1; + public int unitAmount = 1; /**Status effect applied to the spawned unit. Null to disable.*/ - protected StatusEffect effect; + public StatusEffect effect; /**Items this unit spawns with. Null to disable.*/ - protected ItemStack items; + public ItemStack items; public SpawnGroup(UnitType type){ this.type = type; } + public SpawnGroup(){ + //serialization use only + } + /**Returns the amount of units spawned on a specific wave.*/ public int getUnitsSpawned(int wave){ if(wave < begin || wave > end || (wave - begin) % spacing != 0){ @@ -64,6 +74,30 @@ public class SpawnGroup{ return unit; } + @Override + public void write (Json json) { + json.writeValue("type", type.name); + if(begin != 0) json.writeValue("begin", begin); + if(end != never) json.writeValue("end", end); + if(spacing != 1) json.writeValue("spacing", spacing); + if(max != 40) json.writeValue("max", max); + if(unitScaling != never) json.writeValue("scaling", unitScaling); + if(unitAmount != 1) json.writeValue("amount", unitAmount); + if(effect != null) json.writeValue("effect", effect.id); + } + + @Override + public void read (Json json, JsonValue data) { + type = content.getByName(ContentType.unit, data.getString("type", "dagger")); + begin = data.getInt("begin", 0); + end = data.getInt("end", never); + spacing = data.getInt("spacing", 1); + max = data.getInt("spacing", 40); + unitScaling = data.getFloat("scaling", never); + unitAmount = data.getInt("amount", 1); + effect = content.getByID(ContentType.status, data.getInt("effect", -1)); + } + @Override public String toString(){ return "SpawnGroup{" + diff --git a/core/src/io/anuke/mindustry/game/Stats.java b/core/src/io/anuke/mindustry/game/Stats.java index 63e632440c..d99edd78ce 100644 --- a/core/src/io/anuke/mindustry/game/Stats.java +++ b/core/src/io/anuke/mindustry/game/Stats.java @@ -28,9 +28,9 @@ public class Stats{ public RankResult calculateRank(Zone zone, boolean launched){ float score = 0; - //each new launch period adds onto the rank 1.5 'points' + //each new launch period adds onto the rank 'points' if(wavesLasted >= zone.conditionWave){ - score += (float)((wavesLasted - zone.conditionWave) / zone.launchPeriod + 1) * 1.5f; + score += (float)((wavesLasted - zone.conditionWave) / zone.launchPeriod + 1) * 1.3f; } int capacity = zone.loadout.core().itemCapacity; @@ -42,7 +42,7 @@ public class Stats{ frac += Mathf.clamp((float)itemsDelivered.get(item, 0) / capacity) / (float)obtainable.size; } - score += frac*2.4f; + score += frac*2.0f; if(!launched){ score *= 0.5f; diff --git a/core/src/io/anuke/mindustry/graphics/BlockRenderer.java b/core/src/io/anuke/mindustry/graphics/BlockRenderer.java index 8ab693b898..a12ccd624d 100644 --- a/core/src/io/anuke/mindustry/graphics/BlockRenderer.java +++ b/core/src/io/anuke/mindustry/graphics/BlockRenderer.java @@ -165,6 +165,7 @@ public class BlockRenderer{ for(int y = miny; y <= maxy; y++){ boolean expanded = (Math.abs(x - avgx) > rangex || Math.abs(y - avgy) > rangey); Tile tile = world.rawTile(x, y); + if(tile == null) continue; //how is this possible? Block block = tile.block(); if(block != Blocks.air && block.cacheLayer == CacheLayer.normal){ diff --git a/core/src/io/anuke/mindustry/graphics/CacheLayer.java b/core/src/io/anuke/mindustry/graphics/CacheLayer.java index e84bd0a823..9c96f4d3c5 100644 --- a/core/src/io/anuke/mindustry/graphics/CacheLayer.java +++ b/core/src/io/anuke/mindustry/graphics/CacheLayer.java @@ -1,10 +1,36 @@ package io.anuke.mindustry.graphics; +import io.anuke.arc.Core; +import io.anuke.arc.graphics.Color; +import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.arc.graphics.glutils.Shader; + +import static io.anuke.arc.Core.camera; +import static io.anuke.mindustry.Vars.renderer; + public enum CacheLayer{ - water, - lava, - oil, - space, + water{ + @Override + public void begin(){ + beginShader(); + } + + @Override + public void end(){ + endShader(Shaders.water); + } + }, + tar{ + @Override + public void begin(){ + beginShader(); + } + + @Override + public void end(){ + endShader(Shaders.tar); + } + }, normal, walls; @@ -15,4 +41,26 @@ public enum CacheLayer{ public void end(){ } + + void beginShader(){ + if(!Core.settings.getBool("animatedwater")) return; + + renderer.blocks.floor.endc(); + renderer.shieldBuffer.begin(); + Core.graphics.clear(Color.CLEAR); + renderer.blocks.floor.beginc(); + } + + void endShader(Shader shader){ + if(!Core.settings.getBool("animatedwater")) return; + + renderer.blocks.floor.endc(); + renderer.shieldBuffer.end(); + + Draw.shader(shader); + Draw.rect(Draw.wrap(renderer.shieldBuffer.getTexture()), camera.position.x, camera.position.y, camera.width, -camera.height); + Draw.shader(); + + renderer.blocks.floor.beginc(); + } } diff --git a/core/src/io/anuke/mindustry/graphics/FloorRenderer.java b/core/src/io/anuke/mindustry/graphics/FloorRenderer.java index cac217ce05..7bc7acc202 100644 --- a/core/src/io/anuke/mindustry/graphics/FloorRenderer.java +++ b/core/src/io/anuke/mindustry/graphics/FloorRenderer.java @@ -95,6 +95,14 @@ public class FloorRenderer{ endDraw(); } + public void beginc(){ + cbatch.beginDraw(); + } + + public void endc(){ + cbatch.endDraw(); + } + public void beginDraw(){ if(cache == null){ return; @@ -124,8 +132,6 @@ public class FloorRenderer{ int crangex = (int) (camera.width / (chunksize * tilesize)) + 1; int crangey = (int) (camera.height / (chunksize * tilesize)) + 1; - SpriteBatch batch = Core.batch; - Core.batch = cbatch; layer.begin(); for(int x = -crangex; x <= crangex; x++){ @@ -144,7 +150,6 @@ public class FloorRenderer{ } layer.end(); - Core.batch = batch; } private void cacheChunk(int cx, int cy){ @@ -191,6 +196,8 @@ public class FloorRenderer{ tile.block().draw(tile); }else if(floor.cacheLayer == layer && (world.isAccessible(tile.x,tile.y) || tile.block().cacheLayer != CacheLayer.walls || !tile.block().fillsTile)){ floor.draw(tile); + }else if(floor.cacheLayer.ordinal() < layer.ordinal() && layer != CacheLayer.walls){ + floor.drawNonLayer(tile); } } } diff --git a/core/src/io/anuke/mindustry/graphics/MinimapRenderer.java b/core/src/io/anuke/mindustry/graphics/MinimapRenderer.java index 5c938d2b8c..7eac43461c 100644 --- a/core/src/io/anuke/mindustry/graphics/MinimapRenderer.java +++ b/core/src/io/anuke/mindustry/graphics/MinimapRenderer.java @@ -137,7 +137,7 @@ public class MinimapRenderer implements Disposable{ private int colorFor(Tile tile){ tile = tile.target(); - return MapIO.colorFor(tile.floor(), tile.block(), tile.getTeam()); + return MapIO.colorFor(tile.floor(), tile.block(), tile.ore(), tile.getTeam()); } @Override diff --git a/core/src/io/anuke/mindustry/graphics/OverlayRenderer.java b/core/src/io/anuke/mindustry/graphics/OverlayRenderer.java index af8ad777c2..c0975f3b79 100644 --- a/core/src/io/anuke/mindustry/graphics/OverlayRenderer.java +++ b/core/src/io/anuke/mindustry/graphics/OverlayRenderer.java @@ -10,6 +10,7 @@ import io.anuke.arc.math.geom.Vector2; import io.anuke.arc.util.Time; import io.anuke.arc.util.Tmp; import io.anuke.mindustry.content.Blocks; +import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.entities.type.Player; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.input.InputHandler; @@ -35,18 +36,30 @@ public class OverlayRenderer{ public void drawTop(){ - for(Player player : playerGroup.all()){ - if(Core.settings.getBool("indicators") && player != players[0] && player.getTeam() == players[0].getTeam()){ - if(!rect.setSize(Core.camera.width * 0.9f, Core.camera.height * 0.9f) - .setCenter(Core.camera.position.x, Core.camera.position.y).contains(player.x, player.y)){ + if(Core.settings.getBool("indicators")){ + for(Player player : playerGroup.all()){ + if(player != players[0] && player.getTeam() == players[0].getTeam()){ + if(!rect.setSize(Core.camera.width * 0.9f, Core.camera.height * 0.9f) + .setCenter(Core.camera.position.x, Core.camera.position.y).contains(player.x, player.y)){ - Tmp.v1.set(player.x, player.y).sub(Core.camera.position.x, Core.camera.position.y).setLength(indicatorLength); + Tmp.v1.set(player.x, player.y).sub(Core.camera.position.x, Core.camera.position.y).setLength(indicatorLength); - Lines.stroke(2f, player.getTeam().color); - Lines.lineAngle(Core.camera.position.x + Tmp.v1.x, Core.camera.position.y + Tmp.v1.y, Tmp.v1.angle(), 4f); - Draw.reset(); + Lines.stroke(2f, player.getTeam().color); + Lines.lineAngle(Core.camera.position.x + Tmp.v1.x, Core.camera.position.y + Tmp.v1.y, Tmp.v1.angle(), 4f); + Draw.reset(); + } } } + + Units.allUnits(unit -> { + if(unit != players[0] && unit.getTeam() != players[0].getTeam() && !rect.setSize(Core.camera.width * 0.9f, Core.camera.height * 0.9f).setCenter(Core.camera.position.x, Core.camera.position.y).contains(unit.x, unit.y)){ + Tmp.v1.set(unit.x, unit.y).sub(Core.camera.position.x, Core.camera.position.y).setLength(indicatorLength); + + Lines.stroke(1f, unit.getTeam().color); + Lines.lineAngle(Core.camera.position.x + Tmp.v1.x, Core.camera.position.y + Tmp.v1.y, Tmp.v1.angle(), 3f); + Draw.reset(); + } + }); } for(Player player : players){ diff --git a/core/src/io/anuke/mindustry/graphics/Pal.java b/core/src/io/anuke/mindustry/graphics/Pal.java index b5c17c8604..37de7b50b0 100644 --- a/core/src/io/anuke/mindustry/graphics/Pal.java +++ b/core/src/io/anuke/mindustry/graphics/Pal.java @@ -5,6 +5,7 @@ import io.anuke.arc.graphics.Color; public class Pal{ public static final Color + items = Color.valueOf("2ea756"), command = Color.valueOf("eab678"), bulletYellow = Color.valueOf("ffeec9"), diff --git a/core/src/io/anuke/mindustry/graphics/Shaders.java b/core/src/io/anuke/mindustry/graphics/Shaders.java index 223cf38dee..7839716f71 100644 --- a/core/src/io/anuke/mindustry/graphics/Shaders.java +++ b/core/src/io/anuke/mindustry/graphics/Shaders.java @@ -14,6 +14,7 @@ public class Shaders{ public static UnitBuild build; public static FogShader fog; public static MenuShader menu; + public static SurfaceShader water, tar; public static void init(){ shadow = new Shadow(); @@ -22,6 +23,8 @@ public class Shaders{ build = new UnitBuild(); fog = new FogShader(); menu = new MenuShader(); + water = new SurfaceShader("water"); + tar = new SurfaceShader("tar"); } public static class MenuShader extends LoadShader{ @@ -123,6 +126,20 @@ public class Shaders{ Core.camera.height ); } } + + public static class SurfaceShader extends LoadShader{ + + public SurfaceShader(String frag){ + super(frag, "default"); + } + + @Override + public void apply(){ + setUniformf("camerapos", Core.camera.position.x - Core.camera.width / 2, Core.camera.position.y - Core.camera.height / 2); + setUniformf("screensize", Core.camera.width, Core.camera.height); + setUniformf("time", Time.time()); + } + } public static class LoadShader extends Shader{ public LoadShader(String frag, String vert){ diff --git a/core/src/io/anuke/mindustry/input/Binding.java b/core/src/io/anuke/mindustry/input/Binding.java index 3e4068dfb2..5600c5f213 100644 --- a/core/src/io/anuke/mindustry/input/Binding.java +++ b/core/src/io/anuke/mindustry/input/Binding.java @@ -17,12 +17,10 @@ public enum Binding implements KeyBind{ rotate(new Axis(KeyCode.SCROLL)), pick(KeyCode.MOUSE_MIDDLE), dash(KeyCode.SHIFT_LEFT), - drop_unit(KeyCode.SHIFT_LEFT), gridMode(KeyCode.GRAVE), gridModeShift(KeyCode.ALT_LEFT), zoom_hold(KeyCode.CONTROL_LEFT, "view"), zoom(new Axis(KeyCode.SCROLL)), - zoom_minimap(new Axis(KeyCode.MINUS, KeyCode.PLUS)), menu(Core.app.getType() == ApplicationType.Android ? KeyCode.BACK : KeyCode.ESCAPE), pause(KeyCode.SPACE), toggle_menus(KeyCode.C), diff --git a/core/src/io/anuke/mindustry/input/DesktopInput.java b/core/src/io/anuke/mindustry/input/DesktopInput.java index 2abb278ff9..4c22050f54 100644 --- a/core/src/io/anuke/mindustry/input/DesktopInput.java +++ b/core/src/io/anuke/mindustry/input/DesktopInput.java @@ -164,7 +164,7 @@ public class DesktopInput extends InputHandler{ renderer.scaleCamera(Core.input.axisTap(Binding.zoom)); } - renderer.minimap.zoomBy(-Core.input.axisTap(Binding.zoom_minimap)); + //renderer.minimap.zoomBy(-Core.input.axisTap(Binding.zoom_minimap)); if(player.isDead()) return; diff --git a/core/src/io/anuke/mindustry/input/InputHandler.java b/core/src/io/anuke/mindustry/input/InputHandler.java index 71a0001de8..75a773d16f 100644 --- a/core/src/io/anuke/mindustry/input/InputHandler.java +++ b/core/src/io/anuke/mindustry/input/InputHandler.java @@ -230,9 +230,9 @@ public abstract class InputHandler implements InputProcessor{ boolean canMine(Tile tile){ return !Core.scene.hasMouse() - && tile.floor().itemDrop != null && tile.floor().itemDrop.hardness <= player.mech.drillPower + && tile.drop() != null && tile.drop().hardness <= player.mech.drillPower && !tile.floor().playerUnmineable - && player.acceptsItem(tile.floor().itemDrop) + && player.acceptsItem(tile.drop()) && tile.block() == Blocks.air && player.dst(tile.worldx(), tile.worldy()) <= Player.mineDistance; } diff --git a/core/src/io/anuke/mindustry/input/MobileInput.java b/core/src/io/anuke/mindustry/input/MobileInput.java index bd9350b4dd..cb2b4a3900 100644 --- a/core/src/io/anuke/mindustry/input/MobileInput.java +++ b/core/src/io/anuke/mindustry/input/MobileInput.java @@ -19,6 +19,7 @@ import io.anuke.arc.math.geom.Vector2; import io.anuke.arc.scene.ui.layout.Table; import io.anuke.arc.util.Align; import io.anuke.arc.util.Time; +import io.anuke.arc.util.Tmp; import io.anuke.mindustry.content.Blocks; import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.core.GameState.State; @@ -218,6 +219,23 @@ public class MobileInput extends InputHandler implements GestureListener{ } } + void drawPlaceArrow(Block block, int x, int y, int rotation){ + if(!block.rotate) return; + Draw.color(!validPlace(x, y, block, rotation) ? Pal.removeBack : Pal.accentBack); + Draw.rect(Core.atlas.find("place-arrow"), + x * tilesize + block.offset(), + y * tilesize + block.offset() - 1, + Core.atlas.find("place-arrow").getWidth() * Draw.scl, + Core.atlas.find("place-arrow").getHeight() * Draw.scl, rotation * 90 - 90); + + Draw.color(!validPlace(x, y, block, rotation) ? Pal.remove : Pal.accent); + Draw.rect(Core.atlas.find("place-arrow"), + x * tilesize + block.offset(), + y * tilesize + block.offset(), + Core.atlas.find("place-arrow").getWidth() * Draw.scl, + Core.atlas.find("place-arrow").getHeight() * Draw.scl, rotation * 90 - 90); + } + //endregion //region UI and drawing @@ -245,8 +263,7 @@ public class MobileInput extends InputHandler implements GestureListener{ //rotate button table.addImageButton("icon-arrow", "clear-partial", 16 * 2f, () -> rotation = Mathf.mod(rotation + 1, 4)) - .update(i -> i.getImage().setRotationOrigin(rotation * 90, Align.center)) - .visible(() -> block != null && block.rotate); + .update(i -> i.getImage().setRotationOrigin(rotation * 90, Align.center)).visible(() -> block != null && block.rotate); //confirm button table.addImageButton("icon-check", "clear-partial", 16 * 2f, () -> { @@ -311,10 +328,18 @@ public class MobileInput extends InputHandler implements GestureListener{ request.scale = Mathf.lerpDelta(request.scale, 1f, 0.2f); request.redness = Mathf.lerpDelta(request.redness, 0f, 0.2f); }else{ - request.scale = Mathf.lerpDelta(request.scale, 0.5f, 0.1f); - request.redness = Mathf.lerpDelta(request.redness, 1f, 0.2f); + request.scale = Mathf.lerpDelta(request.scale, 0.6f, 0.1f); + request.redness = Mathf.lerpDelta(request.redness, 0.9f, 0.2f); } + Tmp.c1.set(Draw.getMixColor()); + + if(!request.remove && request == lastPlaced && request.block != null){ + Draw.mixcol(); + drawPlaceArrow(request.block, tile.x, tile.y, request.rotation); + } + + Draw.mixcol(Tmp.c1, 1f); drawRequest(request); //draw last placed request @@ -334,12 +359,19 @@ public class MobileInput extends InputHandler implements GestureListener{ //draw placing if(mode == placing && block != null){ + NormalizeDrawResult dresult = PlaceUtils.normalizeDrawArea(block, lineStartX, lineStartY, tileX, tileY, true, maxLength, lineScale); Lines.rect(dresult.x, dresult.y, dresult.x2 - dresult.x, dresult.y2 - dresult.y); NormalizeResult result = PlaceUtils.normalizeArea(lineStartX, lineStartY, tileX, tileY, rotation, true, maxLength); + { + int x = lineStartX + result.getLength() * Mathf.sign(tileX - lineStartX) * Mathf.num(result.isX()); + int y = lineStartY + result.getLength() * Mathf.sign(tileY - lineStartY) * Mathf.num(!result.isX()); + drawPlaceArrow(block, x, y, result.rotation); + } + //go through each cell and draw the block to place if valid for(int i = 0; i <= result.getLength(); i += block.size){ int x = lineStartX + i * Mathf.sign(tileX - lineStartX) * Mathf.num(result.isX()); diff --git a/core/src/io/anuke/mindustry/io/BundleLoader.java b/core/src/io/anuke/mindustry/io/BundleLoader.java index 497d7f14cb..ba11207bf1 100644 --- a/core/src/io/anuke/mindustry/io/BundleLoader.java +++ b/core/src/io/anuke/mindustry/io/BundleLoader.java @@ -39,6 +39,8 @@ public class BundleLoader{ } private static void loadBundle(){ + if(headless) return; + try{ //try loading external bundle FileHandle handle = Core.files.local("bundle"); diff --git a/core/src/io/anuke/mindustry/io/MapIO.java b/core/src/io/anuke/mindustry/io/MapIO.java index 2e83e14d31..6db9e18a2f 100644 --- a/core/src/io/anuke/mindustry/io/MapIO.java +++ b/core/src/io/anuke/mindustry/io/MapIO.java @@ -3,75 +3,341 @@ package io.anuke.mindustry.io; import io.anuke.arc.collection.IntIntMap; import io.anuke.arc.collection.ObjectMap; import io.anuke.arc.collection.ObjectMap.Entry; +import io.anuke.arc.files.FileHandle; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.Pixmap; import io.anuke.arc.graphics.Pixmap.Format; -import io.anuke.arc.util.Pack; -import io.anuke.arc.util.Structs; +import io.anuke.arc.math.Mathf; +import io.anuke.arc.util.*; import io.anuke.mindustry.content.Blocks; +import io.anuke.mindustry.game.MappableContent; import io.anuke.mindustry.game.Team; +import io.anuke.mindustry.game.Version; import io.anuke.mindustry.maps.Map; -import io.anuke.mindustry.maps.MapMeta; -import io.anuke.mindustry.maps.MapTileData; -import io.anuke.mindustry.maps.MapTileData.DataPosition; -import io.anuke.mindustry.maps.MapTileData.TileDataMarker; import io.anuke.mindustry.type.ContentType; +import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.Block; +import io.anuke.mindustry.world.CachedTile; import io.anuke.mindustry.world.LegacyColorMapper; import io.anuke.mindustry.world.LegacyColorMapper.LegacyBlock; +import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.blocks.BlockPart; +import io.anuke.mindustry.world.blocks.Floor; -import java.io.DataInputStream; -import java.io.DataOutputStream; -import java.io.IOException; -import java.io.OutputStream; +import java.io.*; +import java.util.Arrays; +import java.util.zip.DeflaterOutputStream; +import java.util.zip.InflaterInputStream; +import static io.anuke.mindustry.Vars.bufferSize; import static io.anuke.mindustry.Vars.content; -/** - * Reads and writes map files. - */ +/** Reads and writes map files.*/ public class MapIO{ - private static final int version = 0; - private static IntIntMap defaultBlockMap = new IntIntMap(); + public static final int version = 1; - private static void loadDefaultBlocks(){ - for(Block block : content.blocks()){ - defaultBlockMap.put(block.id, block.id); + private static final int[] pngHeader = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A}; + private static ObjectMap missingBlocks; + + private static void initBlocks(){ + if(missingBlocks != null) return; + + //stainedRocks, stainedRocksRed, stainedRocksYellow, stainedStoneYellow, stainedBoulder, + missingBlocks = ObjectMap.of( + "stained-stone", Blocks.shale, + "stained-stone-red", Blocks.shale, + "stained-stone-yellow", Blocks.shale, + "stained-rocks", Blocks.shaleRocks, + "stained-boulder", Blocks.shaleBoulder, + "stained-rocks-red", Blocks.shaleRocks, + "stained-rocks-yellow", Blocks.shaleRocks + ); + } + + public static boolean isImage(FileHandle file){ + try(InputStream stream = file.read(32)){ + for(int i1 : pngHeader){ + if(stream.read() != i1){ + return false; + } + } + return true; + }catch(IOException e){ + return false; } } - public static Pixmap generatePixmap(MapTileData data){ - Pixmap pixmap = new Pixmap(data.width(), data.height(), Format.RGBA8888); - data.position(0, 0); + public static Pixmap generatePreview(Map map) throws IOException{ + Time.mark(); + Pixmap floor = new Pixmap(map.width, map.height, Format.RGBA8888); + Pixmap wall = new Pixmap(map.width, map.height, Format.RGBA8888); + int black = Color.rgba8888(Color.BLACK); + CachedTile tile = new CachedTile(){ + @Override + public void setFloor(Floor type){ + floor.drawPixel(x, floor.getHeight() - 1 - y, colorFor(type, Blocks.air, Blocks.air, getTeam())); + } - TileDataMarker marker = data.newDataMarker(); + @Override + public void setOreByte(byte b){ + if(b != 0) floor.drawPixel(x, floor.getHeight() - 1 - y, colorFor(floor(), Blocks.air, content.block(b), getTeam())); + } - for(int y = 0; y < data.height(); y++){ - for(int x = 0; x < data.width(); x++){ - data.read(marker); - Block floor = content.block(marker.floor); - Block wall = content.block(marker.wall); - int color = colorFor(floor, wall, Team.all[marker.team]); - pixmap.drawPixel(x, pixmap.getHeight() - 1 - y, color); + @Override + protected void changed(){ + super.changed(); + int c = colorFor(Blocks.air, block(), Blocks.air, getTeam()); + if(c != black) wall.drawPixel(x, floor.getHeight() - 1 - y, c); + } + }; + readTiles(map, (x, y) -> { + tile.x = (short)x; + tile.y = (short)y; + return tile; + }); + floor.drawPixmap(wall, 0, 0); + wall.dispose(); + return floor; + } + + public static Pixmap generatePreview(Tile[][] tiles){ + Pixmap pixmap = new Pixmap(tiles.length, tiles[0].length, Format.RGBA8888); + for(int x = 0; x < pixmap.getWidth(); x++){ + for(int y = 0; y < pixmap.getHeight(); y++){ + Tile tile = tiles[x][y]; + pixmap.drawPixel(x, pixmap.getHeight() - 1 - y, colorFor(tile.floor(), tile.block(), tile.ore(), tile.getTeam())); } } - - data.position(0, 0); - return pixmap; } - /**Reads a pixmap in the old (3.5) map format.*/ - public static MapTileData readLegacyPixmap(Pixmap pixmap){ - MapTileData data = new MapTileData(pixmap.getWidth(), pixmap.getHeight()); + public static int colorFor(Block floor, Block wall, Block ore, Team team){ + if(wall.synthetic()){ + return team.intColor; + } + return Color.rgba8888(wall.solid ? wall.color : ore == Blocks.air ? floor.color : ore.color); + } - for(int x = 0; x < data.width(); x++){ - for(int y = 0; y < data.height(); y++){ + public static void writeMap(FileHandle file, Map map, Tile[][] tiles) throws IOException{ + OutputStream output = file.write(false, bufferSize); + + { + DataOutputStream stream = new DataOutputStream(output); + stream.writeInt(version); + stream.writeInt(Version.build); + stream.writeShort(tiles.length); + stream.writeShort(tiles[0].length); + stream.writeByte((byte)map.tags.size); + + for(Entry entry : map.tags.entries()){ + stream.writeUTF(entry.key); + stream.writeUTF(entry.value); + } + } + + try(DataOutputStream stream = new DataOutputStream(new DeflaterOutputStream(output))){ + int width = map.width, height = map.height; + + SaveIO.getSaveWriter().writeContentHeader(stream); + + //floor first + for(int i = 0; i < tiles.length * tiles[0].length; i++){ + Tile tile = tiles[i % width][i / width]; + stream.writeByte(tile.getFloorID()); + stream.writeByte(tile.getOreByte()); + int consecutives = 0; + + for(int j = i + 1; j < width * height && consecutives < 255; j++){ + Tile nextTile = tiles[j % width][j / width]; + + if(nextTile.getFloorID() != tile.getFloorID() || nextTile.block() != Blocks.air || nextTile.getOreByte() != tile.getOreByte()){ + break; + } + + consecutives++; + } + + stream.writeByte(consecutives); + i += consecutives; + } + + //then blocks + for(int i = 0; i < tiles.length * tiles[0].length; i++){ + Tile tile = tiles[i % width][i / width]; + stream.writeByte(tile.getBlockID()); + + if(tile.block() instanceof BlockPart){ + stream.writeByte(tile.link); + }else if(tile.entity != null){ + stream.writeByte(Pack.byteByte(tile.getTeamID(), tile.getRotation())); //team + rotation + stream.writeShort(/*(short)tile.entity.health*/tile.block().health); //health + tile.entity.writeConfig(stream); + }else{ + //write consecutive non-entity blocks + int consecutives = 0; + + for(int j = i + 1; j < width * height && consecutives < 255; j++){ + Tile nextTile = tiles[j % width][j / width]; + + if(nextTile.block() != tile.block()){ + break; + } + + consecutives++; + } + + stream.writeByte(consecutives); + i += consecutives; + } + } + } + } + + public static Map readMap(FileHandle file, boolean custom) throws IOException{ + try(DataInputStream stream = new DataInputStream(file.read(1024))){ + ObjectMap tags = new ObjectMap<>(); + + //meta is uncompressed + int version = stream.readInt(); + if(version == 0){ + return readLegacyMap(file, custom); + } + int build = stream.readInt(); + short width = stream.readShort(), height = stream.readShort(); + byte tagAmount = stream.readByte(); + + for(int i = 0; i < tagAmount; i++){ + String name = stream.readUTF(); + String value = stream.readUTF(); + tags.put(name, value); + } + + return new Map(file, width, height, tags, custom, version, build); + } + } + + /**Reads tiles from a map, version-agnostic.*/ + public static void readTiles(Map map, Tile[][] tiles) throws IOException{ + readTiles(map, (x, y) -> tiles[x][y]); + } + + /**Reads tiles from a map, version-agnostic.*/ + public static void readTiles(Map map, TileProvider tiles) throws IOException{ + if(map.version == 0){ + readLegacyMmapTiles(map.file, tiles); + }else if(map.version == version){ + readTiles(map.file, map.width, map.height, tiles); + }else{ + throw new IOException("Unknown map version. What?"); + } + } + + /**Reads tiles from a map in the new build-65 format.*/ + private static void readTiles(FileHandle file, int width, int height, Tile[][] tiles) throws IOException{ + readTiles(file, width, height, (x, y) -> tiles[x][y]); + } + + /**Reads tiles from a map in the new build-65 format.*/ + private static void readTiles(FileHandle file, int width, int height, TileProvider tiles) throws IOException{ + try(BufferedInputStream input = file.read(bufferSize)){ + + //read map + { + DataInputStream stream = new DataInputStream(input); + + stream.readInt(); //version + stream.readInt(); //build + stream.readInt(); //width + height + byte tagAmount = stream.readByte(); + + for(int i = 0; i < tagAmount; i++){ + stream.readUTF(); //key + stream.readUTF(); //val + } + } + + try(DataInputStream stream = new DataInputStream(new InflaterInputStream(input))){ + + MappableContent[][] c = SaveIO.getSaveWriter().readContentHeader(stream); + + try{ + content.setTemporaryMapper(c); + + //read floor and create tiles first + for(int i = 0; i < width * height; i++){ + int x = i % width, y = i / width; + byte floorid = stream.readByte(); + byte oreid = stream.readByte(); + int consecutives = stream.readUnsignedByte(); + + Tile tile = tiles.get(x, y); + tile.setFloor((Floor)content.block(floorid)); + tile.setOre(content.block(oreid)); + + for(int j = i + 1; j < i + 1 + consecutives; j++){ + int newx = j % width, newy = j / width; + Tile newTile = tiles.get(newx, newy); + newTile.setFloor((Floor)content.block(floorid)); + newTile.setOre(content.block(oreid)); + } + + i += consecutives; + } + + //read blocks + for(int i = 0; i < width * height; i++){ + int x = i % width, y = i / width; + Block block = content.block(stream.readByte()); + + Tile tile = tiles.get(x, y); + tile.setBlock(block); + + if(block == Blocks.part){ + tile.link = stream.readByte(); + }else if(tile.entity != null){ + byte tr = stream.readByte(); + short health = stream.readShort(); + + byte team = Pack.leftByte(tr); + byte rotation = Pack.rightByte(tr); + + tile.setTeam(Team.all[team]); + tile.entity.health = /*health*/tile.block().health; + tile.setRotation(rotation); + + tile.entity.readConfig(stream); + }else{ //no entity/part, read consecutives + int consecutives = stream.readUnsignedByte(); + + for(int j = i + 1; j < i + 1 + consecutives; j++){ + int newx = j % width, newy = j / width; + tiles.get(newx, newy).setBlock(block); + } + + i += consecutives; + } + } + + }finally{ + content.setTemporaryMapper(null); + } + } + } + } + + //region legacy IO + + /**Reads a pixmap in the 3.5 pixmap format.*/ + public static void readLegacyPixmap(Pixmap pixmap, Tile[][] tiles){ + for(int x = 0; x < pixmap.getWidth(); x++){ + for(int y = 0; y < pixmap.getHeight(); y++){ int color = pixmap.getPixel(x, pixmap.getHeight() - 1 - y); LegacyBlock block = LegacyColorMapper.get(color); + Tile tile = tiles[x][y]; - data.write(x, y, DataPosition.floor, block.floor.id); - data.write(x, y, DataPosition.wall, block.wall.id); + tile.setFloor(block.floor); + tile.setBlock(block.wall); + if(block.ore != null) tile.setOre(block.ore); //place core if(color == Color.rgba8888(Color.GREEN)){ @@ -80,121 +346,133 @@ public class MapIO{ int worldx = dx - 1 + x; int worldy = dy - 1 + y; + //multiblock parts if(Structs.inBounds(worldx, worldy, pixmap.getWidth(), pixmap.getHeight())){ - data.write(worldx, worldy, DataPosition.wall, Blocks.part.id); - data.write(worldx, worldy, DataPosition.rotationTeam, Pack.byteByte((byte)0, (byte)Team.blue.ordinal())); - data.write(worldx, worldy, DataPosition.link, Pack.byteByte((byte) (dx - 1 + 8), (byte) (dy - 1 + 8))); + Tile write = tiles[worldx][worldy]; + write.setBlock(Blocks.part); + write.setTeam(Team.blue); + write.setLinkByte(Pack.byteByte((byte) (dx - 1 + 8), (byte) (dy - 1 + 8))); } } } - data.write(x, y, DataPosition.wall, Blocks.coreShard.id); - data.write(x, y, DataPosition.rotationTeam, Pack.byteByte((byte)0, (byte)Team.blue.ordinal())); + //actual core parts + tile.setBlock(Blocks.coreShard); + tile.setTeam(Team.blue); } } } - - return data; } - public static void writeMap(OutputStream stream, ObjectMap tags, MapTileData data) throws IOException{ - if(defaultBlockMap == null){ - loadDefaultBlocks(); - } - - MapMeta meta = new MapMeta(version, tags, data.width(), data.height(), defaultBlockMap); - - DataOutputStream ds = new DataOutputStream(stream); - - writeMapMeta(ds, meta); - ds.write(data.toArray()); - - ds.close(); + /**Reads a pixmap in the old 4.0 .mmap format.*/ + private static void readLegacyMmapTiles(FileHandle file, Tile[][] tiles) throws IOException{ + readLegacyMmapTiles(file, (x, y) -> tiles[x][y]); } - /** - * Reads tile data, skipping meta. - */ - public static MapTileData readTileData(DataInputStream stream, boolean readOnly) throws IOException{ - MapMeta meta = readMapMeta(stream); - return readTileData(stream, meta, readOnly); - } + /**Reads a mmap in the old 4.0 .mmap format.*/ + private static void readLegacyMmapTiles(FileHandle file, TileProvider tiles) throws IOException{ + try(DataInputStream stream = new DataInputStream(file.read(bufferSize))){ + stream.readInt(); //version + byte tagAmount = stream.readByte(); + for(int i = 0; i < tagAmount; i++){ + stream.readUTF(); //key + stream.readUTF(); //val + } - /** - * Does not skip meta. Call after reading meta. - */ - public static MapTileData readTileData(DataInputStream stream, MapMeta meta, boolean readOnly) throws IOException{ - byte[] bytes = new byte[stream.available()]; - stream.readFully(bytes); - return new MapTileData(bytes, meta.width, meta.height, meta.blockMap, readOnly); - } - - /** - * Reads tile data, skipping meta tags. - */ - public static MapTileData readTileData(Map map, boolean readOnly){ - try(DataInputStream ds = new DataInputStream(map.stream.get())){ - return MapIO.readTileData(ds, readOnly); - }catch(IOException e){ - throw new RuntimeException(e); - } - } - - public static MapMeta readMapMeta(DataInputStream stream) throws IOException{ - ObjectMap tags = new ObjectMap<>(); - IntIntMap map = new IntIntMap(); - - int version = stream.readInt(); - - byte tagAmount = stream.readByte(); - - for(int i = 0; i < tagAmount; i++){ - String name = stream.readUTF(); - String value = stream.readUTF(); - tags.put(name, value); - } - - short blocks = stream.readShort(); - for(int i = 0; i < blocks; i++){ - short id = stream.readShort(); - String name = stream.readUTF(); - Block block = content.getByName(ContentType.block, name); - if(block == null){ - block = Blocks.air; + initBlocks(); + + //block id -> real id map + IntIntMap map = new IntIntMap(); + IntIntMap oreMap = new IntIntMap(); + + short blocks = stream.readShort(); + for(int i = 0; i < blocks; i++){ + short id = stream.readShort(); + String name = stream.readUTF(); + Block block = content.getByName(ContentType.block, name); + if(block == null){ + //substitute for replacement in missingBlocks if possible + if(missingBlocks.containsKey(name)){ + block = missingBlocks.get(name); + }else if(name.startsWith("ore-")){ //an ore floor combination + String[] split = name.split("-"); + String itemName = split[1], floorName = Strings.join("-", Arrays.copyOfRange(split, 2, split.length)); + Item item = content.getByName(ContentType.item, itemName); + Block oreBlock = item == null ? null : content.getByName(ContentType.block, "ore-" + item.name); + Block floor = missingBlocks.get(floorName, content.getByName(ContentType.block, floorName)); + if(oreBlock != null && floor != null){ + oreMap.put(id, oreBlock.id); + block = floor; + }else{ + block = Blocks.air; + } + }else{ + block = Blocks.air; + } + + } + map.put(id, block.id); + } + short width = stream.readShort(), height = stream.readShort(); + + for(int y = 0; y < height; y++){ + for(int x = 0; x < width; x++){ + Tile tile = tiles.get(x, y); + byte floorb = stream.readByte(); + byte blockb = stream.readByte(); + byte link = stream.readByte(); + byte rotTeamb = stream.readByte(); + stream.readByte();//unused stuff + + tile.setFloor((Floor)content.block(map.get(floorb, 0))); + tile.setBlock(content.block(map.get(blockb, 0))); + tile.setRotation(Pack.leftByte(rotTeamb)); + if(tile.block().synthetic()){ + tile.setTeam(Team.all[Mathf.clamp(Pack.rightByte(rotTeamb), 0, Team.all.length)]); + } + + if(tile.block() == Blocks.part){ + tile.setLinkByte(link); + } + + if(oreMap.containsKey(floorb)){ + tile.setOre(content.block(oreMap.get(floorb, 0))); + } + } } - map.put(id, block.id); } - - int width = stream.readShort(); - int height = stream.readShort(); - - return new MapMeta(version, tags, width, height, map); } - public static void writeMapMeta(DataOutputStream stream, MapMeta meta) throws IOException{ - stream.writeInt(meta.version); - stream.writeByte((byte) meta.tags.size); + private static Map readLegacyMap(FileHandle file, boolean custom) throws IOException{ + try(DataInputStream stream = new DataInputStream(file.read(bufferSize))){ + ObjectMap tags = new ObjectMap<>(); - for(Entry entry : meta.tags.entries()){ - stream.writeUTF(entry.key); - stream.writeUTF(entry.value); + int version = stream.readInt(); + if(version != 0) throw new IOException("Attempted to read non-legacy map in legacy method!"); + byte tagAmount = stream.readByte(); + + for(int i = 0; i < tagAmount; i++){ + String name = stream.readUTF(); + String value = stream.readUTF(); + tags.put(name, value); + } + + short blocks = stream.readShort(); + for(int i = 0; i < blocks; i++){ + stream.readShort(); + stream.readUTF(); + } + short width = stream.readShort(), height = stream.readShort(); + + //note that build 64 is the default build of all maps <65; while this can be inaccurate it's better than nothing + return new Map(file, width, height, tags, custom, 0, 64); } - - stream.writeShort(content.blocks().size); - for(Block block : content.blocks()){ - stream.writeShort(block.id); - stream.writeUTF(block.name); - } - - stream.writeShort(meta.width); - stream.writeShort(meta.height); } - public static int colorFor(Block floor, Block wall, Team team){ - if(wall.synthetic()){ - return team.intColor; - } - return Color.rgba8888(wall.solid ? wall.color : floor.color); + //endregion + + interface TileProvider{ + Tile get(int x, int y); } -} +} \ No newline at end of file diff --git a/core/src/io/anuke/mindustry/io/SaveFileVersion.java b/core/src/io/anuke/mindustry/io/SaveFileVersion.java index e304816eef..289f7b85b1 100644 --- a/core/src/io/anuke/mindustry/io/SaveFileVersion.java +++ b/core/src/io/anuke/mindustry/io/SaveFileVersion.java @@ -14,8 +14,8 @@ import io.anuke.mindustry.game.Rules; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.gen.Serialization; import io.anuke.mindustry.type.ContentType; +import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.blocks.BlockPart; import java.io.DataInputStream; import java.io.DataOutputStream; @@ -43,18 +43,37 @@ public abstract class SaveFileVersion{ } public void writeMap(DataOutputStream stream) throws IOException{ - //write world size stream.writeShort(world.width()); stream.writeShort(world.height()); + //floor first for(int i = 0; i < world.width() * world.height(); i++){ Tile tile = world.tile(i % world.width(), i / world.width()); - stream.writeByte(tile.getFloorID()); + stream.writeByte(tile.getOreByte()); + int consecutives = 0; + + for(int j = i + 1; j < world.width() * world.height() && consecutives < 255; j++){ + Tile nextTile = world.tile(j % world.width(), j / world.width()); + + if(nextTile.getFloorID() != tile.getFloorID() || nextTile.getOreByte() != tile.getOreByte()){ + break; + } + + consecutives++; + } + + stream.writeByte(consecutives); + i += consecutives; + } + + //blocks + for(int i = 0; i < world.width() * world.height(); i++){ + Tile tile = world.tile(i % world.width(), i / world.width()); stream.writeByte(tile.getBlockID()); - if(tile.block() instanceof BlockPart){ + if(tile.block() == Blocks.part){ stream.writeByte(tile.link); }else if(tile.entity != null){ stream.writeByte(Pack.byteByte(tile.getTeamID(), tile.getRotation())); //team + rotation @@ -67,13 +86,14 @@ public abstract class SaveFileVersion{ tile.entity.writeConfig(stream); tile.entity.write(stream); - }else if(tile.block() == Blocks.air){ + }else{ + //write consecutive non-entity blocks int consecutives = 0; for(int j = i + 1; j < world.width() * world.height() && consecutives < 255; j++){ Tile nextTile = world.tile(j % world.width(), j / world.width()); - if(nextTile.getFloorID() != tile.getFloorID() || nextTile.block() != Blocks.air){ + if(nextTile.block() != tile.block()){ break; } @@ -94,14 +114,35 @@ public abstract class SaveFileVersion{ Tile[][] tiles = world.createTiles(width, height); + //read floor and create tiles first for(int i = 0; i < width * height; i++){ int x = i % width, y = i / width; byte floorid = stream.readByte(); - byte wallid = stream.readByte(); + byte oreid = stream.readByte(); + int consecutives = stream.readUnsignedByte(); + Block ore = content.block(oreid); - Tile tile = new Tile(x, y, floorid, wallid); + tiles[x][y] = new Tile(x, y, floorid, (byte)0); + tiles[x][y].setOre(ore); - if(wallid == Blocks.part.id){ + for(int j = i + 1; j < i + 1 + consecutives; j++){ + int newx = j % width, newy = j / width; + Tile newTile = new Tile(newx, newy, floorid, (byte)0); + newTile.setOre(ore); + tiles[newx][newy] = newTile; + } + + i += consecutives; + } + + //read blocks + for(int i = 0; i < width * height; i++){ + int x = i % width, y = i / width; + Block block = content.block(stream.readByte()); + Tile tile = tiles[x][y]; + tile.setBlock(block); + + if(block == Blocks.part){ tile.link = stream.readByte(); }else if(tile.entity != null){ byte tr = stream.readByte(); @@ -121,19 +162,16 @@ public abstract class SaveFileVersion{ tile.entity.readConfig(stream); tile.entity.read(stream); - }else if(wallid == 0){ + }else{ int consecutives = stream.readUnsignedByte(); for(int j = i + 1; j < i + 1 + consecutives; j++){ int newx = j % width, newy = j / width; - Tile newTile = new Tile(newx, newy, floorid, wallid); - tiles[newx][newy] = newTile; + tiles[newx][newy].setBlock(block); } i += consecutives; } - - tiles[x][y] = tile; } content.setTemporaryMapper(null); diff --git a/core/src/io/anuke/mindustry/io/SaveIO.java b/core/src/io/anuke/mindustry/io/SaveIO.java index 10846a4268..f7c5b50320 100644 --- a/core/src/io/anuke/mindustry/io/SaveIO.java +++ b/core/src/io/anuke/mindustry/io/SaveIO.java @@ -48,7 +48,7 @@ public class SaveIO{ } public static DataInputStream getSlotStream(int slot){ - return new DataInputStream(new InflaterInputStream(fileFor(slot).read())); + return new DataInputStream(new InflaterInputStream(fileFor(slot).read(bufferSize))); } public static boolean isSaveValid(int slot){ @@ -60,7 +60,7 @@ public class SaveIO{ } public static boolean isSaveValid(FileHandle file){ - return isSaveValid(new DataInputStream(new InflaterInputStream(file.read()))); + return isSaveValid(new DataInputStream(new InflaterInputStream(file.read(bufferSize)))); } public static boolean isSaveValid(DataInputStream stream){ @@ -95,7 +95,7 @@ public class SaveIO{ } public static void write(FileHandle file){ - write(new DeflaterOutputStream(file.write(false)){ + write(new DeflaterOutputStream(file.write(false, bufferSize)){ byte[] tmp = {0}; public void write(int var1) throws IOException { @@ -120,12 +120,12 @@ public class SaveIO{ public static void load(FileHandle file) throws SaveException{ try{ //try and load; if any exception at all occurs - load(new InflaterInputStream(file.read())); + load(new InflaterInputStream(file.read(bufferSize))); }catch(SaveException e){ e.printStackTrace(); FileHandle backup = file.sibling(file.name() + "-backup." + file.extension()); if(backup.exists()){ - load(new InflaterInputStream(backup.read())); + load(new InflaterInputStream(backup.read(bufferSize))); }else{ throw new SaveException(e.getCause()); } diff --git a/core/src/io/anuke/mindustry/io/SaveMeta.java b/core/src/io/anuke/mindustry/io/SaveMeta.java index cfe0be8231..f88746605f 100644 --- a/core/src/io/anuke/mindustry/io/SaveMeta.java +++ b/core/src/io/anuke/mindustry/io/SaveMeta.java @@ -19,7 +19,7 @@ public class SaveMeta{ this.build = build; this.timestamp = timestamp; this.timePlayed = timePlayed; - this.map = world.maps.getByName(map); + this.map = world.maps.all().find(m -> m.name().equals(map)); this.wave = wave; this.rules = rules; } diff --git a/core/src/io/anuke/mindustry/io/TypeIO.java b/core/src/io/anuke/mindustry/io/TypeIO.java index 937440a425..c88bce34eb 100644 --- a/core/src/io/anuke/mindustry/io/TypeIO.java +++ b/core/src/io/anuke/mindustry/io/TypeIO.java @@ -2,21 +2,24 @@ package io.anuke.mindustry.io; import io.anuke.annotations.Annotations.ReadClass; import io.anuke.annotations.Annotations.WriteClass; +import io.anuke.arc.graphics.Color; import io.anuke.mindustry.entities.Effects; import io.anuke.mindustry.entities.Effects.Effect; import io.anuke.mindustry.entities.Entities; -import io.anuke.arc.graphics.Color; -import io.anuke.mindustry.entities.type.Player; -import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.entities.bullet.Bullet; import io.anuke.mindustry.entities.bullet.BulletType; import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest; import io.anuke.mindustry.entities.traits.ShooterTrait; import io.anuke.mindustry.entities.type.BaseUnit; +import io.anuke.mindustry.entities.type.Player; +import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.net.Packets.AdminAction; import io.anuke.mindustry.net.Packets.KickReason; -import io.anuke.mindustry.type.*; +import io.anuke.mindustry.type.ContentType; +import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.type.Liquid; +import io.anuke.mindustry.type.Mech; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Pos; import io.anuke.mindustry.world.Tile; @@ -25,7 +28,6 @@ import java.io.DataInput; import java.io.DataOutput; import java.io.IOException; import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; import static io.anuke.mindustry.Vars.*; @@ -253,7 +255,7 @@ public class TypeIO{ @WriteClass(String.class) public static void writeString(ByteBuffer buffer, String string){ if(string != null){ - byte[] bytes = string.getBytes(StandardCharsets.UTF_8); + byte[] bytes = string.getBytes(charset); buffer.putShort((short) bytes.length); buffer.put(bytes); }else{ @@ -267,7 +269,7 @@ public class TypeIO{ if(slength != -1){ byte[] bytes = new byte[slength]; buffer.get(bytes); - return new String(bytes, StandardCharsets.UTF_8); + return new String(bytes, charset); }else{ return null; } @@ -289,7 +291,7 @@ public class TypeIO{ public static void writeStringData(DataOutput buffer, String string) throws IOException{ if(string != null){ - byte[] bytes = string.getBytes(StandardCharsets.UTF_8); + byte[] bytes = string.getBytes(charset); buffer.writeShort((short) bytes.length); buffer.write(bytes); }else{ @@ -302,7 +304,7 @@ public class TypeIO{ if(slength != -1){ byte[] bytes = new byte[slength]; buffer.readFully(bytes); - return new String(bytes, StandardCharsets.UTF_8); + return new String(bytes, charset); }else{ return null; } diff --git a/core/src/io/anuke/mindustry/io/versions/Save16.java b/core/src/io/anuke/mindustry/io/versions/Save16.java index 40c2c2f371..466da0d648 100644 --- a/core/src/io/anuke/mindustry/io/versions/Save16.java +++ b/core/src/io/anuke/mindustry/io/versions/Save16.java @@ -1,13 +1,11 @@ package io.anuke.mindustry.io.versions; -import io.anuke.arc.util.Strings; +import io.anuke.arc.collection.ObjectMap; import io.anuke.arc.util.Time; import io.anuke.mindustry.game.Version; import io.anuke.mindustry.gen.Serialization; import io.anuke.mindustry.io.SaveFileVersion; import io.anuke.mindustry.maps.Map; -import io.anuke.mindustry.type.ContentType; -import io.anuke.mindustry.type.Zone; import java.io.DataInputStream; import java.io.DataOutputStream; @@ -29,14 +27,11 @@ public class Save16 extends SaveFileVersion{ //general state state.rules = Serialization.readRules(stream); - //load zone spawn patterns if applicable - if(content.getByID(ContentType.zone, state.rules.zone) != null){ - state.rules.spawns = content.getByID(ContentType.zone, state.rules.zone).rules.get().spawns; - } String mapname = stream.readUTF(); - Map map = world.maps.getByName(mapname); - if(map == null) map = new Map(Strings.capitalize(mapname), 1, 1); + Map map = world.maps.all().find(m -> m.name().equals(mapname)); + if(map == null) map = new Map(customMapDirectory.child(mapname), 1, 1, new ObjectMap<>(), true); world.setMap(map); + state.rules.spawns = map.getWaves(); int wave = stream.readInt(); float wavetime = stream.readFloat(); @@ -62,7 +57,7 @@ public class Save16 extends SaveFileVersion{ //--GENERAL STATE-- Serialization.writeRules(stream, state.rules); - stream.writeUTF(world.getMap().name); //map name + stream.writeUTF(world.getMap().name()); //map name stream.writeInt(state.wave); //wave stream.writeFloat(state.wavetime); //wave countdown diff --git a/core/src/io/anuke/mindustry/maps/Map.java b/core/src/io/anuke/mindustry/maps/Map.java index 2481d42344..b97f30a91e 100644 --- a/core/src/io/anuke/mindustry/maps/Map.java +++ b/core/src/io/anuke/mindustry/maps/Map.java @@ -1,44 +1,111 @@ package io.anuke.mindustry.maps; -import io.anuke.arc.graphics.Texture; +import io.anuke.arc.Core; +import io.anuke.arc.collection.Array; import io.anuke.arc.collection.ObjectMap; -import io.anuke.arc.function.Supplier; +import io.anuke.arc.files.FileHandle; +import io.anuke.arc.graphics.Texture; +import io.anuke.arc.util.Log; +import io.anuke.mindustry.Vars; +import io.anuke.mindustry.game.DefaultWaves; +import io.anuke.mindustry.game.SpawnGroup; +import io.anuke.mindustry.io.MapIO; -import java.io.InputStream; +import static io.anuke.mindustry.Vars.world; -public class Map{ - /** Internal map name. This is the filename, without any extensions.*/ - public final String name; +public class Map implements Comparable{ /** Whether this is a custom map.*/ public final boolean custom; /** Metadata. Author description, display name, etc.*/ - public final MapMeta meta; - /** Supplies a new input stream with the data of this map.*/ - public final Supplier stream; + public final ObjectMap tags; + /** Base file of this map. File can be named anything at all.*/ + public final FileHandle file; + /** Format version.*/ + public final int version; + /** Map width/height, shorts.*/ + public int width, height; /** Preview texture.*/ public Texture texture; + /** Build that this map was created in. -1 = unknown or custom build.*/ + public int build; - public Map(String name, MapMeta meta, boolean custom, Supplier streamSupplier){ - this.name = name; + public Map(FileHandle file, int width, int height, ObjectMap tags, boolean custom, int version, int build){ this.custom = custom; - this.meta = meta; - this.stream = streamSupplier; + this.tags = tags; + this.file = file; + this.width = width; + this.height = height; + this.version = version; + this.build = build; } - public Map(String unknownName, int width, int height){ - this(unknownName, new MapMeta(0, new ObjectMap<>(), width, height, null), true, () -> null); + public Map(FileHandle file, int width, int height, ObjectMap tags, boolean custom, int version){ + this(file, width, height, tags, custom, version, -1); } - public String getDisplayName(){ - return meta.tags.get("name", name); + public Map(FileHandle file, int width, int height, ObjectMap tags, boolean custom){ + this(file, width, height, tags, custom, MapIO.version); + } + + public Array getWaves(){ + if(tags.containsKey("waves")){ + try{ + return world.maps.readWaves(tags.get("waves")); + }catch(Exception e){ + Log.err("Malformed waves: {0}", tags.get("waves")); + e.printStackTrace(); + return DefaultWaves.get(); + } + }else{ + return DefaultWaves.get(); + } + } + + public int getHightScore(){ + return Core.settings.getInt("hiscore" + file.nameWithoutExtension(), 0); + } + + public void setHighScore(int score){ + Core.settings.put("hiscore" + file.nameWithoutExtension(), score); + Vars.data.modified(); + } + + public String author(){ + return tag("author"); + } + + public String description(){ + return tag("description"); + } + + public String name(){ + return tag("name"); + } + + public String tag(String name){ + return tags.containsKey(name) && !tags.get(name).trim().isEmpty() ? tags.get(name): Core.bundle.get("unknown"); + } + + public boolean hasTag(String name){ + return tags.containsKey(name); + } + + @Override + public int compareTo(Map map){ + int type = -Boolean.compare(custom, map.custom); + if(type != 0){ + return type; + }else{ + return name().compareTo(map.name()); + } } @Override public String toString(){ return "Map{" + - "name='" + name + '\'' + + "file='" + file + '\'' + ", custom=" + custom + - ", meta=" + meta + + ", tags=" + tags + '}'; } } diff --git a/core/src/io/anuke/mindustry/maps/MapMeta.java b/core/src/io/anuke/mindustry/maps/MapMeta.java deleted file mode 100644 index 36f815b63f..0000000000 --- a/core/src/io/anuke/mindustry/maps/MapMeta.java +++ /dev/null @@ -1,46 +0,0 @@ -package io.anuke.mindustry.maps; - -import io.anuke.arc.Core; -import io.anuke.arc.collection.IntIntMap; -import io.anuke.arc.collection.ObjectMap; - -//todo: specify preferred game rules here; can be overriden -public class MapMeta{ - public final int version; - public final ObjectMap tags; - public final int width, height; - public final IntIntMap blockMap; - - public MapMeta(int version, ObjectMap tags, int width, int height, IntIntMap blockMap){ - this.version = version; - this.tags = tags; - this.width = width; - this.height = height; - this.blockMap = blockMap; - } - - public String author(){ - return tag("author"); - } - - public String description(){ - return tag("description"); - } - - public String name(){ - return tag("name"); - } - - public String tag(String name){ - return tags.containsKey(name) && !tags.get(name).trim().isEmpty() ? tags.get(name): Core.bundle.get("unknown"); - } - - @Override - public String toString(){ - return "MapMeta{" + - "tags=" + tags + - ", width=" + width + - ", height=" + height + - '}'; - } -} diff --git a/core/src/io/anuke/mindustry/maps/MapTileData.java b/core/src/io/anuke/mindustry/maps/MapTileData.java deleted file mode 100644 index e7c550e919..0000000000 --- a/core/src/io/anuke/mindustry/maps/MapTileData.java +++ /dev/null @@ -1,175 +0,0 @@ -package io.anuke.mindustry.maps; - -import io.anuke.arc.collection.IntIntMap; -import io.anuke.arc.util.Pack; -import io.anuke.arc.util.Structs; -import io.anuke.mindustry.Vars; -import io.anuke.mindustry.content.Blocks; -import io.anuke.mindustry.world.Block; - -import java.nio.ByteBuffer; - -public class MapTileData{ - /** - * Tile size: 5 bytes.
- * 0: ground tile
- * 1: wall tile
- * 2: rotation + team
- * 3: link (x/y)
- * 4: elevation
- */ - private final static int TILE_SIZE = 5; - - private final ByteBuffer buffer; - private final int width, height; - private final boolean readOnly; - - private IntIntMap map; - - public MapTileData(int width, int height){ - this.width = width; - this.height = height; - this.map = null; - this.readOnly = false; - buffer = ByteBuffer.allocate(width * height * TILE_SIZE); - } - - public MapTileData(byte[] bytes, int width, int height, IntIntMap mapping, boolean readOnly){ - buffer = ByteBuffer.wrap(bytes); - this.width = width; - this.height = height; - this.map = mapping; - this.readOnly = readOnly; - - if(mapping != null && !readOnly){ - buffer.position(0); - TileDataMarker marker = new TileDataMarker(); - for(int i = 0; i < width * height; i++){ - read(marker); - - //strip blockparts from map data, as they can be invalid - if(marker.wall == Blocks.part.id){ - marker.wall = Blocks.air.id; - } - - buffer.position(i * TILE_SIZE); - - //write mapped marker - write(marker); - } - - buffer.position(0); - for(int x = 0; x < width; x ++){ - for(int y = 0; y < height; y ++){ - //add missing blockparts - Block drawBlock = Vars.content.block(read(x, y, DataPosition.wall)); - if(drawBlock.isMultiblock()){ - int offsetx = -(drawBlock.size - 1) / 2; - int offsety = -(drawBlock.size - 1) / 2; - for(int dx = 0; dx < drawBlock.size; dx++){ - for(int dy = 0; dy < drawBlock.size; dy++){ - int worldx = dx + offsetx + x; - int worldy = dy + offsety + y; - - if(Structs.inBounds(worldx, worldy, width, height) && !(dx + offsetx == 0 && dy + offsety == 0)){ - write(worldx, worldy, DataPosition.wall, Blocks.part.id); - write(worldx, worldy, DataPosition.link, Pack.byteByte((byte) (dx + offsetx + 8), (byte) (dy + offsety + 8))); - } - } - } - } - } - } - buffer.position(0); - this.map = null; - } - } - - public byte[] toArray(){ - return buffer.array(); - } - - public int width(){ - return width; - } - - public int height(){ - return height; - } - - /** - * Write a byte to a specific position. - */ - public void write(int x, int y, DataPosition position, byte data){ - buffer.put((x + width * y) * TILE_SIZE + position.ordinal(), data); - } - - /** - * Gets a byte at a specific position. - */ - public byte read(int x, int y, DataPosition position){ - return buffer.get((x + width * y) * TILE_SIZE + position.ordinal()); - } - - /** - * Reads and returns the next tile data. - */ - public TileDataMarker read(TileDataMarker marker){ - marker.read(buffer); - return marker; - } - - /** - * Writes this tile data marker. - */ - public void write(TileDataMarker marker){ - marker.write(buffer); - } - - /** - * Sets read position to the specified coordinates - */ - public void position(int x, int y){ - buffer.position((x + width * y) * TILE_SIZE); - } - - public TileDataMarker newDataMarker(){ - return new TileDataMarker(); - } - - public enum DataPosition{ - floor, wall, link, rotationTeam, elevation - } - - public class TileDataMarker{ - public byte floor, wall; - public byte link; - public byte rotation; - public byte team; - public byte elevation; - - public void read(ByteBuffer buffer){ - floor = buffer.get(); - wall = buffer.get(); - link = buffer.get(); - byte rt = buffer.get(); - elevation = buffer.get(); - rotation = Pack.leftByte(rt); - team = Pack.rightByte(rt); - - if(map != null){ - floor = (byte) map.get(floor, Blocks.stone.id); - wall = (byte) map.get(wall, 0); - } - } - - public void write(ByteBuffer buffer){ - if(readOnly) throw new IllegalArgumentException("This data is read-only."); - buffer.put(floor); - buffer.put(wall); - buffer.put(link); - buffer.put(Pack.byteByte(rotation, team)); - buffer.put(elevation); - } - } -} diff --git a/core/src/io/anuke/mindustry/maps/Maps.java b/core/src/io/anuke/mindustry/maps/Maps.java index 2bd7823ad5..ff5fc523cb 100644 --- a/core/src/io/anuke/mindustry/maps/Maps.java +++ b/core/src/io/anuke/mindustry/maps/Maps.java @@ -1,166 +1,211 @@ package io.anuke.mindustry.maps; import io.anuke.arc.Core; +import io.anuke.arc.collection.Array; +import io.anuke.arc.collection.ObjectMap; import io.anuke.arc.files.FileHandle; import io.anuke.arc.graphics.Texture; -import io.anuke.arc.collection.Array; import io.anuke.arc.util.Disposable; -import io.anuke.arc.collection.ObjectMap; -import io.anuke.mindustry.io.MapIO; -import io.anuke.arc.function.Supplier; import io.anuke.arc.util.Log; +import io.anuke.arc.util.Time; +import io.anuke.arc.util.serialization.Json; +import io.anuke.mindustry.game.SpawnGroup; +import io.anuke.mindustry.io.MapIO; +import io.anuke.mindustry.world.Tile; -import java.io.DataInputStream; import java.io.IOException; -import java.io.InputStream; +import java.io.StringWriter; import static io.anuke.mindustry.Vars.*; public class Maps implements Disposable{ - /**List of all built-in maps.*/ - private static final String[] defaultMapNames = {}; - /**Tile format version.*/ - private static final int version = 0; + /** List of all built-in maps. Filenames only.*/ + private static final String[] defaultMapNames = {"fortress"}; + /** All maps stored in an ordered array. */ + private Array maps = new Array<>(); + /** Serializer for meta.*/ + private Json json = new Json(); - /**Maps map names to the real maps.*/ - private ObjectMap maps = new ObjectMap<>(); - /**All maps stored in an ordered array.*/ - private Array allMaps = new Array<>(); - /**Temporary array used for returning things.*/ - private Array returnArray = new Array<>(); + public Maps(){ - /**Returns a list of all maps, including custom ones.*/ + } + + /** Returns a list of all maps, including custom ones. */ public Array all(){ - return allMaps; + return maps; } - /**Returns a list of only custom maps.*/ + /** Returns a list of only custom maps. */ public Array customMaps(){ - returnArray.clear(); - for(Map map : allMaps){ - if(map.custom) returnArray.add(map); - } - return returnArray; + return maps.select(m -> m.custom); } - /**Returns a list of only default maps.*/ + /** Returns a list of only default maps. */ public Array defaultMaps(){ - returnArray.clear(); - for(Map map : allMaps){ - if(!map.custom) returnArray.add(map); - } - return returnArray; + return maps.select(m -> !m.custom); } - /**Returns map by internal name.*/ - public Map getByName(String name){ - return maps.get(name); + public Map byName(String name){ + return maps.find(m -> m.name().equals(name)); } - /**Loads a map from the map folder and returns it. Should only be used for zone maps. - * Does not add this map to the map list.*/ + /** + * Loads a map from the map folder and returns it. Should only be used for zone maps. + * Does not add this map to the map list. + */ public Map loadInternalMap(String name){ FileHandle file = Core.files.internal("maps/" + name + "." + mapExtension); - try(DataInputStream ds = new DataInputStream(file.read())) { - return new Map(name, MapIO.readMapMeta(ds), false, file::read); + try{ + return MapIO.readMap(file, false); }catch(IOException e){ throw new RuntimeException(e); } } - /**Load all maps. Should be called at application start.*/ + /** Load all maps. Should be called at application start. */ public void load(){ + Time.mark(); try{ - for (String name : defaultMapNames) { + for(String name : defaultMapNames){ FileHandle file = Core.files.internal("maps/" + name + "." + mapExtension); - loadMap(file.nameWithoutExtension(), file::read, false); + loadMap(file, false); } - }catch (IOException e){ + }catch(IOException e){ throw new RuntimeException(e); } loadCustomMaps(); + Log.info("Time to load maps: {0}", Time.elapsed()); } - /**Save a map. This updates all values and stored data necessary.*/ - public void saveMap(String name, MapTileData data, ObjectMap tags){ + /** Save a custom map to the directory. This updates all values and stored data necessary. + * The tags are copied to prevent mutation later.*/ + public void saveMap(ObjectMap baseTags, Tile[][] data){ + try{ - //create copy of tags to prevent mutation later - ObjectMap newTags = new ObjectMap<>(); - newTags.putAll(tags); - tags = newTags; + ObjectMap tags = new ObjectMap<>(baseTags); + String name = tags.get("name"); + if(name == null) throw new IllegalArgumentException("Can't save a map with no name. How did this happen?"); + //FileHandle file = customMapDirectory.child(name + "." + mapExtension); + FileHandle file; - FileHandle file = customMapDirectory.child(name + "." + mapExtension); - MapIO.writeMap(file.write(false), tags, data); + //find map with the same exact display name + Map other = maps.find(m -> m.name().equals(name)); - if(maps.containsKey(name)){ - if(maps.get(name).texture != null) { - maps.get(name).texture.dispose(); - maps.get(name).texture = null; + if(other != null){ + //dispose of map if it's already there + if(other.texture != null){ + other.texture.dispose(); + other.texture = null; } - allMaps.removeValue(maps.get(name), true); + maps.remove(other); + file = other.file; + }else{ + file = findFile(); } - Map map = new Map(name, new MapMeta(version, tags, data.width(), data.height(), null), true, getStreamFor(name)); + //create map, write it, etc etc etc + Map map = new Map(file, data.length, data[0].length, tags, true); + MapIO.writeMap(file, map, data); + if(!headless){ - map.texture = new Texture(MapIO.generatePixmap(data)); + map.texture = new Texture(MapIO.generatePreview(data)); } - allMaps.add(map); - - maps.put(name, map); - }catch (IOException e){ + maps.add(map); + maps.sort(); + }catch(IOException e){ throw new RuntimeException(e); } } - /**Removes a map completely.*/ + /** Import a map, then save it. This updates all values and stored data necessary. */ + public void importMap(FileHandle file) throws IOException{ + FileHandle dest = findFile(); + file.copyTo(dest); + + loadMap(dest, true); + } + + /** Removes a map completely. */ public void removeMap(Map map){ if(map.texture != null){ map.texture.dispose(); map.texture = null; } - maps.remove(map.name); - allMaps.removeValue(map, true); - - customMapDirectory.child(map.name + "." + mapExtension).delete(); + maps.remove(map); + map.file.delete(); } - private void loadMap(String name, Supplier supplier, boolean custom) throws IOException{ - try(DataInputStream ds = new DataInputStream(supplier.get())) { - MapMeta meta = MapIO.readMapMeta(ds); - Map map = new Map(name, meta, custom, supplier); - - if (!headless){ - map.texture = new Texture(MapIO.generatePixmap(MapIO.readTileData(ds, meta, true))); - } - - maps.put(map.name, map); - allMaps.add(map); + public String writeWaves(Array groups){ + if(groups == null){ + return "[]"; } + + StringWriter buffer = new StringWriter(); + json.setWriter(buffer); + + json.writeArrayStart(); + for(int i = 0; i < groups.size; i++){ + json.writeObjectStart(SpawnGroup.class, SpawnGroup.class); + groups.get(i).write(json); + json.writeObjectEnd(); + } + json.writeArrayEnd(); + return buffer.toString(); + } + + public Array readWaves(String str){ + return str == null ? null : str.equals("[]") ? new Array<>() : Array.with(json.fromJson(SpawnGroup[].class, str)); + } + + /** Find a new filename to put a map to.*/ + private FileHandle findFile(){ + //find a map name that isn't used. + int i = maps.size; + while(customMapDirectory.child("map_" + i + "." + mapExtension).exists()){ + i ++; + } + return customMapDirectory.child("map_" + i + "." + mapExtension); + } + + private void loadMap(FileHandle file, boolean custom) throws IOException{ + Map map = MapIO.readMap(file, custom); + + if(map.name() == null){ + throw new IOException("Map name cannot be empty! File: " + file); + } + + if(!headless){ + map.texture = new Texture(MapIO.generatePreview(map)); + } + + maps.add(map); + maps.sort(); } private void loadCustomMaps(){ for(FileHandle file : customMapDirectory.list()){ try{ if(file.extension().equalsIgnoreCase(mapExtension)){ - loadMap(file.nameWithoutExtension(), file::read, true); + loadMap(file, true); } - }catch (Exception e){ + }catch(Exception e){ Log.err("Failed to load custom map file '{0}'!", file); Log.err(e); } } } - /**Returns an input stream supplier for a given map name.*/ - private Supplier getStreamFor(String name){ - return customMapDirectory.child(name + "." + mapExtension)::read; - } - @Override - public void dispose() { - + public void dispose(){ + for(Map map : maps){ + if(map.texture != null){ + map.texture.dispose(); + map.texture = null; + } + } + maps.clear(); } } \ No newline at end of file diff --git a/core/src/io/anuke/mindustry/maps/generators/BasicGenerator.java b/core/src/io/anuke/mindustry/maps/generators/BasicGenerator.java index e348bca08b..26a9d62ace 100644 --- a/core/src/io/anuke/mindustry/maps/generators/BasicGenerator.java +++ b/core/src/io/anuke/mindustry/maps/generators/BasicGenerator.java @@ -6,8 +6,6 @@ import io.anuke.arc.util.noise.Simplex; import io.anuke.mindustry.content.Blocks; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.blocks.Floor; -import io.anuke.mindustry.world.blocks.OreBlock; public class BasicGenerator extends RandomGenerator{ private Array ores; @@ -31,13 +29,14 @@ public class BasicGenerator extends RandomGenerator{ public void generate(int x, int y){ floor = Blocks.stone; - if(ores != null && ((Floor) floor).hasOres){ + if(ores != null){ int offsetX = x - 4, offsetY = y + 23; for(int i = ores.size - 1; i >= 0; i--){ Item entry = ores.get(i); if(Math.abs(0.5f - sim.octaveNoise2D(2, 0.7, 1f / (50 + i * 2), offsetX, offsetY)) > 0.23f && Math.abs(0.5f - sim2.octaveNoise2D(1, 1, 1f / (40 + i * 4), offsetX, offsetY)) > 0.32f){ - floor = OreBlock.get(floor, entry); + + //floor = OreBlock.get(floor, entry); break; } } diff --git a/core/src/io/anuke/mindustry/maps/generators/MapGenerator.java b/core/src/io/anuke/mindustry/maps/generators/MapGenerator.java index c083662278..c4087ca2e1 100644 --- a/core/src/io/anuke/mindustry/maps/generators/MapGenerator.java +++ b/core/src/io/anuke/mindustry/maps/generators/MapGenerator.java @@ -9,19 +9,17 @@ import io.anuke.mindustry.content.Blocks; import io.anuke.mindustry.content.Items; import io.anuke.mindustry.io.MapIO; import io.anuke.mindustry.maps.Map; -import io.anuke.mindustry.maps.MapTileData; -import io.anuke.mindustry.maps.MapTileData.TileDataMarker; import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.type.Loadout; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.Floor; -import io.anuke.mindustry.world.blocks.OreBlock; import io.anuke.mindustry.world.blocks.StaticWall; import io.anuke.mindustry.world.blocks.storage.CoreBlock; import io.anuke.mindustry.world.blocks.storage.StorageBlock; -import static io.anuke.mindustry.Vars.content; +import java.io.IOException; + import static io.anuke.mindustry.Vars.world; public class MapGenerator extends Generator{ @@ -73,112 +71,112 @@ public class MapGenerator extends Generator{ public void init(Loadout loadout){ this.loadout = loadout; map = world.maps.loadInternalMap(mapName); - width = map.meta.width; - height = map.meta.height; + width = map.width; + height = map.height; } @Override public void generate(Tile[][] tiles){ - MapTileData data = MapIO.readTileData(map, true); - - data.position(0, 0); - TileDataMarker marker = data.newDataMarker(); - Array players = new Array<>(); - Array enemies = new Array<>(); - - for(int y = 0; y < data.height(); y++){ - for(int x = 0; x < data.width(); x++){ - data.read(marker); - - if(content.block(marker.wall) instanceof CoreBlock){ - players.add(new Point2(x, y)); - marker.wall = 0; + try{ + for(int x = 0; x < width; x++){ + for(int y = 0; y < height; y++){ + tiles[x][y] = new Tile(x, y); } - - if(enemySpawns != -1 && content.block(marker.wall) == Blocks.spawn){ - enemies.add(new Point2(x, y)); - marker.wall = 0; - } - - tiles[x][y] = new Tile(x, y, marker.floor, marker.wall == Blocks.part.id ? 0 : marker.wall, marker.rotation, marker.team); } - } - Simplex simplex = new Simplex(Mathf.random(99999)); + MapIO.readTiles(map, tiles); + Array players = new Array<>(); + Array enemies = new Array<>(); - for(int x = 0; x < data.width(); x++){ - for(int y = 0; y < data.height(); y++){ - final double scl = 10; - Tile tile = tiles[x][y]; - int newX = Mathf.clamp((int)(simplex.octaveNoise2D(1, 1, 1.0 / scl, x, y) * distortion + x), 0, data.width()-1); - int newY = Mathf.clamp((int)(simplex.octaveNoise2D(1, 1, 1.0 / scl, x + 9999, y + 9999) * distortion + y), 0, data.height()-1); + for(int x = 0; x < width; x++){ + for(int y = 0; y < height; y++){ + if(tiles[x][y].block() instanceof CoreBlock){ + players.add(new Point2(x, y)); + tiles[x][y].setBlock(Blocks.air); + } - if((tile.block() instanceof StaticWall + if(tiles[x][y].block() == Blocks.spawn){ + enemies.add(new Point2(x, y)); + tiles[x][y].setBlock(Blocks.air); + } + } + } + + Simplex simplex = new Simplex(Mathf.random(99999)); + + for(int x = 0; x < width; x++){ + for(int y = 0; y < height; y++){ + final double scl = 10; + Tile tile = tiles[x][y]; + int newX = Mathf.clamp((int)(simplex.octaveNoise2D(1, 1, 1.0 / scl, x, y) * distortion + x), 0, width - 1); + int newY = Mathf.clamp((int)(simplex.octaveNoise2D(1, 1, 1.0 / scl, x + 9999, y + 9999) * distortion + y), 0, height - 1); + + if((tile.block() instanceof StaticWall && tiles[newX][newY].block() instanceof StaticWall) || (tile.block() == Blocks.air && !tiles[newX][newY].block().synthetic()) || (tiles[newX][newY].block() == Blocks.air && tile.block() instanceof StaticWall)){ - tile.setBlock(tiles[newX][newY].block()); - } - - if(distortFloor){ - tile.setFloor(tiles[newX][newY].floor()); - } - - for(Decoration decor : decorations){ - if(tile.block() == Blocks.air && !(decor.wall instanceof Floor) && tile.floor() == decor.floor && Mathf.chance(decor.chance)){ - tile.setBlock(decor.wall); - }else if(tile.floor() == decor.floor && decor.wall instanceof Floor && Mathf.chance(decor.chance)){ - tile.setFloor((Floor)decor.wall); + tile.setBlock(tiles[newX][newY].block()); } - } - if(tile.block() instanceof StorageBlock && !(tile.block() instanceof CoreBlock)){ - for(ItemStack stack : storageDrops){ - if(Mathf.chance(0.3)){ - tile.entity.items.add(stack.item, Math.min(Mathf.random(stack.amount), tile.block().itemCapacity)); + if(distortFloor){ + tile.setFloor(tiles[newX][newY].floor()); + } + + for(Decoration decor : decorations){ + if(tile.block() == Blocks.air && !(decor.wall instanceof Floor) && tile.floor() == decor.floor && Mathf.chance(decor.chance)){ + tile.setBlock(decor.wall); + }else if(tile.floor() == decor.floor && decor.wall instanceof Floor && Mathf.chance(decor.chance)){ + tile.setFloor((Floor)decor.wall); } } - } - } - } - if(enemySpawns != -1){ - if(enemySpawns > enemies.size){ - throw new IllegalArgumentException("Enemy spawn pool greater than map spawn number."); - } - - enemies.shuffle(); - for(int i = 0; i < enemySpawns; i++){ - Point2 point = enemies.get(i); - tiles[point.x][point.y].setBlock(Blocks.spawn); - - int rad = 10, frad = 12; - - for(int x = -rad; x <= rad; x++){ - for(int y = -rad; y <= rad; y++){ - int wx = x + point.x, wy = y + point.y; - double dst = Mathf.dst(x, y); - if(dst < frad && Structs.inBounds(wx, wy, tiles) && (dst <= rad || Mathf.chance(0.5))){ - Tile tile = tiles[wx][wy]; - if(tile.floor() instanceof OreBlock){ - OreBlock block = (OreBlock)tile.floor(); - tile.setFloor(block.base); + if(tile.block() instanceof StorageBlock && !(tile.block() instanceof CoreBlock)){ + for(ItemStack stack : storageDrops){ + if(Mathf.chance(0.3)){ + tile.entity.items.add(stack.item, Math.min(Mathf.random(stack.amount), tile.block().itemCapacity)); } } } } } + + if(enemySpawns != -1){ + if(enemySpawns > enemies.size){ + throw new IllegalArgumentException("Enemy spawn pool greater than map spawn number."); + } + + enemies.shuffle(); + for(int i = 0; i < enemySpawns; i++){ + Point2 point = enemies.get(i); + tiles[point.x][point.y].setBlock(Blocks.spawn); + + int rad = 10, frad = 12; + + for(int x = -rad; x <= rad; x++){ + for(int y = -rad; y <= rad; y++){ + int wx = x + point.x, wy = y + point.y; + double dst = Mathf.dst(x, y); + if(dst < frad && Structs.inBounds(wx, wy, tiles) && (dst <= rad || Mathf.chance(0.5))){ + Tile tile = tiles[wx][wy]; + tile.clearOre(); + } + } + } + } + } + + Point2 core = players.random(); + if(core == null){ + throw new IllegalArgumentException("All zone maps must have a core."); + } + + loadout.setup(core.x, core.y); + + world.prepareTiles(tiles); + world.setMap(map); + }catch(IOException e){ + throw new RuntimeException(e); } - - Point2 core = players.random(); - if(core == null){ - throw new IllegalArgumentException("All zone maps must have a core."); - } - - loadout.setup(core.x, core.y); - - world.prepareTiles(tiles); - world.setMap(map); } public static class Decoration{ diff --git a/core/src/io/anuke/mindustry/net/NetworkIO.java b/core/src/io/anuke/mindustry/net/NetworkIO.java index e9bc9308f1..45e46aae3b 100644 --- a/core/src/io/anuke/mindustry/net/NetworkIO.java +++ b/core/src/io/anuke/mindustry/net/NetworkIO.java @@ -3,8 +3,8 @@ package io.anuke.mindustry.net; import io.anuke.arc.Core; import io.anuke.arc.collection.ObjectMap; import io.anuke.arc.collection.ObjectMap.Entry; -import io.anuke.mindustry.entities.Entities; import io.anuke.arc.util.Time; +import io.anuke.mindustry.entities.Entities; import io.anuke.mindustry.entities.type.Player; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.game.Teams; @@ -17,7 +17,6 @@ import io.anuke.mindustry.world.Tile; import java.io.*; import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; import static io.anuke.mindustry.Vars.*; @@ -28,10 +27,10 @@ public class NetworkIO{ try(DataOutputStream stream = new DataOutputStream(os)){ //--GENERAL STATE-- Serialization.writeRules(stream, state.rules); - stream.writeUTF(world.getMap().name); //map name + stream.writeUTF(world.getMap().name()); //map name //write tags - ObjectMap tags = world.getMap().meta.tags; + ObjectMap tags = world.getMap().tags; stream.writeByte(tags.size); for(Entry entry : tags.entries()){ stream.writeUTF(entry.key); @@ -106,7 +105,7 @@ public class NetworkIO{ //map world.spawner.read(stream); SaveIO.getSaveWriter().readMap(stream); - world.setMap(new Map(map, 0, 0)); + world.setMap(new Map(customMapDirectory.child(map), 0, 0, new ObjectMap<>(), true)); state.teams = new Teams(); @@ -142,24 +141,24 @@ public class NetworkIO{ int maxlen = 32; String host = (headless ? "Server" : players[0].name); - String map = world.getMap() == null ? "None" : world.getMap().name; + String map = world.getMap() == null ? "None" : world.getMap().name(); host = host.substring(0, Math.min(host.length(), maxlen)); map = map.substring(0, Math.min(map.length(), maxlen)); ByteBuffer buffer = ByteBuffer.allocate(128); - buffer.put((byte) host.getBytes(StandardCharsets.UTF_8).length); - buffer.put(host.getBytes(StandardCharsets.UTF_8)); + buffer.put((byte) host.getBytes(charset).length); + buffer.put(host.getBytes(charset)); - buffer.put((byte) map.getBytes(StandardCharsets.UTF_8).length); - buffer.put(map.getBytes(StandardCharsets.UTF_8)); + buffer.put((byte) map.getBytes(charset).length); + buffer.put(map.getBytes(charset)); buffer.putInt(playerGroup.size()); buffer.putInt(state.wave); buffer.putInt(Version.build); - buffer.put((byte)Version.type.getBytes(StandardCharsets.UTF_8).length); - buffer.put(Version.type.getBytes(StandardCharsets.UTF_8)); + buffer.put((byte)Version.type.getBytes(charset).length); + buffer.put(Version.type.getBytes(charset)); return buffer; } @@ -172,8 +171,8 @@ public class NetworkIO{ byte[] mb = new byte[mlength]; buffer.get(mb); - String host = new String(hb, StandardCharsets.UTF_8); - String map = new String(mb, StandardCharsets.UTF_8); + String host = new String(hb, charset); + String map = new String(mb, charset); int players = buffer.getInt(); int wave = buffer.getInt(); @@ -181,7 +180,7 @@ public class NetworkIO{ byte tlength = buffer.get(); byte[] tb = new byte[tlength]; buffer.get(tb); - String vertype = new String(tb, StandardCharsets.UTF_8); + String vertype = new String(tb, charset); return new Host(host, hostAddress, map, wave, players, version, vertype); } diff --git a/core/src/io/anuke/mindustry/type/Item.java b/core/src/io/anuke/mindustry/type/Item.java index f1f63d560d..fea86c85bc 100644 --- a/core/src/io/anuke/mindustry/type/Item.java +++ b/core/src/io/anuke/mindustry/type/Item.java @@ -5,12 +5,12 @@ import io.anuke.arc.collection.Array; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.scene.ui.layout.Table; -import io.anuke.arc.util.Log; -import io.anuke.arc.util.Strings; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.game.UnlockableContent; -import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.ui.ContentDisplay; +import io.anuke.mindustry.world.blocks.Floor; +import io.anuke.mindustry.world.blocks.OreBlock; + +import static io.anuke.mindustry.Vars.content; public class Item extends UnlockableContent implements Comparable{ public final Color color; @@ -26,15 +26,11 @@ public class Item extends UnlockableContent implements Comparable{ public float radioactivity; /**drill hardness of the item*/ public int hardness = 0; - /**the burning color of this item. TODO unused; implement*/ - public Color flameColor = Pal.darkFlame.cpy(); /** * base material cost of this item, used for calculating place times * 1 cost = 1 tick added to build time */ public float cost = 3f; - /**Whether this item has ores generated for it.*/ - public boolean genOre = false; /**If true, item is always unlocked.*/ public boolean alwaysUnlocked = false; @@ -42,11 +38,6 @@ public class Item extends UnlockableContent implements Comparable{ super(name); this.color = color; this.description = Core.bundle.getOrNull("item." + this.name + ".description"); - - if(!Core.bundle.has("item." + this.name + ".name")){ - Log.err("Warning: item '" + name + "' is missing a localized name. Add the following to bundle.properties:"); - Log.err("item." + this.name + ".name = " + Strings.capitalize(name.replace('-', '_'))); - } } public void load(){ @@ -111,6 +102,6 @@ public class Item extends UnlockableContent implements Comparable{ /**Allocates a new array containing all items the generate ores.*/ public static Array getAllOres(){ - return Vars.content.items().select(i -> i.genOre); + return content.blocks().select(b -> b instanceof OreBlock).map(b -> ((Floor)b).itemDrop); } } diff --git a/core/src/io/anuke/mindustry/type/Loadout.java b/core/src/io/anuke/mindustry/type/Loadout.java index 312a5b4d4e..26303254b2 100644 --- a/core/src/io/anuke/mindustry/type/Loadout.java +++ b/core/src/io/anuke/mindustry/type/Loadout.java @@ -3,13 +3,10 @@ package io.anuke.mindustry.type; import io.anuke.arc.collection.Array; import io.anuke.arc.collection.IntMap; import io.anuke.mindustry.content.Blocks; -import io.anuke.mindustry.content.Items; import io.anuke.mindustry.game.Content; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Pos; import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.blocks.Floor; -import io.anuke.mindustry.world.blocks.OreBlock; import io.anuke.mindustry.world.blocks.storage.CoreBlock; import static io.anuke.mindustry.Vars.defaultTeam; @@ -27,7 +24,7 @@ public class Loadout extends Content{ put('2', new BlockEntry(Blocks.coreFoundation)); put('3', new BlockEntry(Blocks.coreNucleus)); - put('C', new BlockEntry(Blocks.mechanicalDrill, Items.copper)); + put('C', new BlockEntry(Blocks.mechanicalDrill, Blocks.oreCopper)); }}; private final IntMap blocks = new IntMap<>(); @@ -79,8 +76,7 @@ public class Loadout extends Content{ tile.setRotation((byte)entry.value.rotation); if(entry.value.ore != null){ for(Tile t : tile.getLinkedTiles(outArray)){ - Floor floor = t.floor(); - t.setFloor(OreBlock.get(floor, entry.value.ore) == null ? OreBlock.get(Blocks.stone, entry.value.ore) : OreBlock.get(floor, entry.value.ore)); + t.setOre(entry.value.ore); } } } @@ -93,10 +89,10 @@ public class Loadout extends Content{ static class BlockEntry{ final Block block; - final Item ore; + final Block ore; final int rotation; - BlockEntry(Block block, Item ore){ + BlockEntry(Block block, Block ore){ this.block = block; this.ore = ore; this.rotation = 0; diff --git a/core/src/io/anuke/mindustry/type/UnitType.java b/core/src/io/anuke/mindustry/type/UnitType.java index 0ffbc9f177..d187380fb0 100644 --- a/core/src/io/anuke/mindustry/type/UnitType.java +++ b/core/src/io/anuke/mindustry/type/UnitType.java @@ -5,8 +5,6 @@ import io.anuke.arc.collection.ObjectSet; import io.anuke.arc.function.Supplier; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.scene.ui.layout.Table; -import io.anuke.arc.util.Log; -import io.anuke.arc.util.Strings; import io.anuke.mindustry.content.Items; import io.anuke.mindustry.entities.traits.TypeTrait; import io.anuke.mindustry.entities.type.BaseUnit; @@ -46,11 +44,6 @@ public class UnitType extends UnlockableContent{ this.description = Core.bundle.getOrNull("unit." + name + ".description"); TypeTrait.registerType(type, mainConstructor); - - if(!Core.bundle.has("unit." + this.name + ".name")){ - Log.err("Warning: unit '" + name + "' is missing a localized name. Add the follow to bundle.properties:"); - Log.err("unit." + this.name + ".name=" + Strings.capitalize(name.replace('-', '_'))); - } } @Override diff --git a/core/src/io/anuke/mindustry/ui/Bar.java b/core/src/io/anuke/mindustry/ui/Bar.java index a29ce6d4cb..cbd2b7b0f9 100644 --- a/core/src/io/anuke/mindustry/ui/Bar.java +++ b/core/src/io/anuke/mindustry/ui/Bar.java @@ -78,6 +78,7 @@ public class Bar extends Element{ GlyphLayout lay = Pools.obtain(GlyphLayout.class, GlyphLayout::new); lay.setText(font, name); + font.setColor(Color.WHITE); font.draw(name, x + width/2f - lay.width/2f, y + height/2f + lay.height/2f + 1); Pools.free(lay); diff --git a/core/src/io/anuke/mindustry/ui/Links.java b/core/src/io/anuke/mindustry/ui/Links.java index 8e538759a7..5f47c61a5a 100644 --- a/core/src/io/anuke/mindustry/ui/Links.java +++ b/core/src/io/anuke/mindustry/ui/Links.java @@ -8,7 +8,7 @@ public class Links{ private static void createLinks(){ links = new LinkEntry[]{ - new LinkEntry("discord", "https://discord.gg/BKADYds", Color.valueOf("7289da")), + new LinkEntry("discord", "https://discord.gg/mindustry", Color.valueOf("7289da")), new LinkEntry("trello", "https://trello.com/b/aE2tcUwF", Color.valueOf("026aa7")), new LinkEntry("wiki", "http://mindustry.wikia.com/wiki/Mindustry_Wiki", Color.valueOf("0f142f")), new LinkEntry("itch.io", "https://anuke.itch.io/mindustry", Color.valueOf("fa5c5c")), diff --git a/core/src/io/anuke/mindustry/ui/dialogs/CustomGameDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/CustomGameDialog.java index c068eae79d..18f05306c8 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/CustomGameDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/CustomGameDialog.java @@ -104,9 +104,9 @@ public class CustomGameDialog extends FloatingDialog{ image.getImageCell().size(images); image.top(); image.row(); - image.add("[accent]" + map.getDisplayName()).pad(3f).growX().wrap().get().setAlignment(Align.center, Align.center); + image.add("[accent]" + map.name()).pad(3f).growX().wrap().get().setAlignment(Align.center, Align.center); image.row(); - image.label((() -> Core.bundle.format("level.highscore", Core.settings.getInt("hiscore" + map.name, 0)))).pad(3f); + image.label((() -> Core.bundle.format("level.highscore", map.getHightScore()))).pad(3f); BorderImage border = new BorderImage(map.texture, 3f); border.setScaling(Scaling.fit); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/DatabaseDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/DatabaseDialog.java index 1a6e383dd3..41adede89b 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/DatabaseDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/DatabaseDialog.java @@ -48,7 +48,7 @@ public class DatabaseDialog extends FloatingDialog{ list.left(); int maxWidth = UIUtils.portrait() ? 7 : 13; - int size = 8 * 4; + int size = 8 * 5; int count = 0; diff --git a/core/src/io/anuke/mindustry/ui/dialogs/DeployDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/DeployDialog.java index ea3594e79c..617ad236dc 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/DeployDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/DeployDialog.java @@ -75,7 +75,7 @@ public class DeployDialog extends FloatingDialog{ show(); } }); - }).size(200f).get(); + }).size(230f).get(); b[0] = button; String color = "[lightgray]"; diff --git a/core/src/io/anuke/mindustry/ui/dialogs/LoadDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/LoadDialog.java index 1bfccbc6df..5b4b7f778c 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/LoadDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/LoadDialog.java @@ -113,7 +113,7 @@ public class LoadDialog extends FloatingDialog{ button.defaults().padBottom(3); button.row(); - button.add(Core.bundle.format("save.map", color + (slot.getMap() == null ? Core.bundle.get("unknown") : slot.getMap().meta.name()))); + button.add(Core.bundle.format("save.map", color + (slot.getMap() == null ? Core.bundle.get("unknown") : slot.getMap().name()))); button.row(); button.add(Core.bundle.format("save.wave", color + slot.getWave())); button.row(); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java index 4b79828534..a98770f023 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java @@ -15,12 +15,8 @@ import io.anuke.mindustry.Vars; import io.anuke.mindustry.core.Platform; import io.anuke.mindustry.io.MapIO; import io.anuke.mindustry.maps.Map; -import io.anuke.mindustry.maps.MapMeta; -import io.anuke.mindustry.maps.MapTileData; import io.anuke.mindustry.ui.BorderImage; -import java.io.DataInputStream; - import static io.anuke.mindustry.Vars.*; public class MapsDialog extends FloatingDialog{ @@ -33,27 +29,34 @@ public class MapsDialog extends FloatingDialog{ buttons.addImageTextButton("$editor.importmap", "icon-add", 14 * 2, () -> { Platform.instance.showFileChooser("$editor.importmap", "Map File", file -> { try{ - DataInputStream stream = new DataInputStream(file.read()); - MapMeta meta = MapIO.readMapMeta(stream); - MapTileData data = MapIO.readTileData(stream, meta, true); - stream.close(); + Map map = MapIO.readMap(file, true); + String name = map.tags.get("name"); + if(name == null){ + ui.showError("$editor.errorname"); + return; + } - String name = meta.tags.get("name", file.nameWithoutExtension()); + Map conflict = world.maps.all().find(m -> m.name().equals(name)); - if(world.maps.getByName(name) != null && !world.maps.getByName(name).custom){ + if(conflict != null && !conflict.custom){ ui.showError(Core.bundle.format("editor.import.exists", name)); - }else if(world.maps.getByName(name) != null){ + }else if(conflict != null){ ui.showConfirm("$confirm", "$editor.overwrite.confirm", () -> { - world.maps.saveMap(name, data, meta.tags); - setup(); + try{ + world.maps.importMap(file); + setup(); + }catch(Exception e){ + ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, false))); + Log.err(e); + } }); }else{ - world.maps.saveMap(name, data, meta.tags); + world.maps.importMap(file); setup(); } }catch(Exception e){ - ui.showError(Core.bundle.format("editor.errorimageload", Strings.parseException(e, false))); + ui.showError(Core.bundle.format("editor.errorload", Strings.parseException(e, false))); Log.err(e); } }, true, mapExtension); @@ -89,7 +92,7 @@ public class MapsDialog extends FloatingDialog{ TextButton button = maps.addButton("", "clear", () -> showMapInfo(map)).width(mapsize).pad(8).get(); button.clearChildren(); button.margin(9); - button.add(map.meta.tags.get("name", map.name)).width(mapsize - 18f).center().get().setEllipsis(true); + button.add(map.name()).width(mapsize - 18f).center().get().setEllipsis(true); button.row(); button.addImage("white").growX().pad(4).color(Color.GRAY); button.row(); @@ -129,24 +132,22 @@ public class MapsDialog extends FloatingDialog{ t.add("$editor.name").padRight(10).color(Color.GRAY).padTop(0); t.row(); - t.add(map.meta.tags.get("name", map.name)).growX().wrap().padTop(2); + t.add(map.name()).growX().wrap().padTop(2); t.row(); t.add("$editor.author").padRight(10).color(Color.GRAY); t.row(); - t.add(map.meta.author()).growX().wrap().padTop(2); + t.add(map.author()).growX().wrap().padTop(2); t.row(); t.add("$editor.description").padRight(10).color(Color.GRAY).top(); t.row(); - t.add(map.meta.description()).growX().wrap().padTop(2); - t.row(); - t.add("$editor.oregen.info").padRight(10).color(Color.GRAY); + t.add(map.description()).growX().wrap().padTop(2); }).height(mapsize).width(mapsize); table.row(); table.addImageTextButton("$editor.openin", "icon-load-map", 16 * 2, () -> { try{ - Vars.ui.editor.beginEditMap(map.stream.get()); + Vars.ui.editor.beginEditMap(map.file); dialog.hide(); hide(); }catch(Exception e){ @@ -156,7 +157,7 @@ public class MapsDialog extends FloatingDialog{ }).fillX().height(54f).marginLeft(10); table.addImageTextButton("$delete", "icon-trash-16", 16 * 2, () -> { - ui.showConfirm("$confirm", Core.bundle.format("map.delete", map.name), () -> { + ui.showConfirm("$confirm", Core.bundle.format("map.delete", map.name()), () -> { world.maps.removeMap(map); dialog.hide(); setup(); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java index 8b99145120..60e0ad707e 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java @@ -120,6 +120,7 @@ public class SettingsMenuDialog extends SettingsDialog{ void addSettings(){ //TODO add when sound works again //sound.volumePrefs(); + sound.add("[LIGHT_GRAY]there is no sound implemented in v4 yet"); game.screenshakePref(); game.checkPref("effects", true); @@ -194,6 +195,7 @@ public class SettingsMenuDialog extends SettingsDialog{ graphics.checkPref("fps", false); graphics.checkPref("indicators", true); + graphics.checkPref("animatedwater", !mobile); graphics.checkPref("lasers", true); } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/TechTreeDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/TechTreeDialog.java index 5401b901f6..d1fb9813fe 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/TechTreeDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/TechTreeDialog.java @@ -1,12 +1,12 @@ package io.anuke.mindustry.ui.dialogs; import io.anuke.arc.Core; +import io.anuke.arc.collection.Array; import io.anuke.arc.collection.ObjectSet; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.Lines; import io.anuke.arc.math.Interpolation; -import io.anuke.arc.scene.Element; import io.anuke.arc.scene.Group; import io.anuke.arc.scene.actions.Actions; import io.anuke.arc.scene.event.Touchable; @@ -35,16 +35,14 @@ public class TechTreeDialog extends FloatingDialog{ public TechTreeDialog(){ super(""); - TreeLayout layout = new TreeLayout(); - layout.gapBetweenLevels = Unit.dp.scl(60f); - layout.gapBetweenNodes = Unit.dp.scl(40f); - layout.layout(root); - titleTable.remove(); margin(0f).marginBottom(8); cont.stack(new View(), items = new ItemsDisplay()).grow(); - shown(() -> checkNodes(root)); + shown(() -> { + checkNodes(root); + treeLayout(); + }); hidden(ui.deploy::setup); addCloseButton(); @@ -59,6 +57,25 @@ public class TechTreeDialog extends FloatingDialog{ drawDefaultBackground(x, y); } + void treeLayout(){ + TreeLayout layout = new TreeLayout(); + layout.gapBetweenLevels = Unit.dp.scl(60f); + layout.gapBetweenNodes = Unit.dp.scl(40f); + LayoutNode node = new LayoutNode(root, null); + layout.layout(node); + copyInfo(node); + } + + void copyInfo(LayoutNode node){ + node.node.x = node.x; + node.node.y = node.y; + if(node.children != null){ + for(LayoutNode child : node.children){ + copyInfo(child); + } + } + } + void checkNodes(TechTreeNode node){ boolean locked = locked(node.node); if(!locked) node.visible = true; @@ -71,24 +88,13 @@ public class TechTreeDialog extends FloatingDialog{ } void showToast(String info){ - int maxIndex = 0; - - for(Element e : Core.scene.root.getChildren()){ - if("toast".equals(e.getName())){ - maxIndex = Math.max(maxIndex, (Integer)e.getUserObject() + 1); - } - } - - int m = maxIndex; - Table table = new Table(); - table.actions(Actions.fadeOut(7f, Interpolation.fade), Actions.removeActor()); + table.actions(Actions.fadeOut(0.5f, Interpolation.fade), Actions.removeActor()); table.top().add(info); table.setName("toast"); - table.setUserObject(maxIndex); table.update(() -> { table.toFront(); - table.setPosition(Core.graphics.getWidth()/2f, Core.graphics.getHeight() - 21 - m*20f, Align.top); + table.setPosition(Core.graphics.getWidth()/2f, Core.graphics.getHeight() - 21, Align.top); }); Core.scene.add(table); } @@ -97,6 +103,19 @@ public class TechTreeDialog extends FloatingDialog{ return node.block.locked(); } + class LayoutNode extends TreeNode{ + final TechTreeNode node; + + LayoutNode(TechTreeNode node, LayoutNode parent){ + this.node = node; + this.parent = parent; + this.width = this.height = nodeSize; + if(node.children != null){ + children = Array.with(node.children).select(n -> n.visible).map(t -> new LayoutNode(t, this)).toArray(LayoutNode.class); + } + } + } + class TechTreeNode extends TreeNode{ final TechNode node; boolean visible = true; @@ -126,6 +145,7 @@ public class TechTreeDialog extends FloatingDialog{ for(TechTreeNode node : nodes){ ImageButton button = new ImageButton(node.node.block.icon(Icon.medium), "node"); + button.visible(() -> node.visible); button.clicked(() -> { if(mobile){ hoverNode = button; @@ -174,7 +194,9 @@ public class TechTreeDialog extends FloatingDialog{ showToast(Core.bundle.format("researched", node.block.localizedName)); checkNodes(root); hoverNode = null; + treeLayout(); rebuild(); + Core.scene.act(); } void rebuild(){ @@ -242,9 +264,11 @@ public class TechTreeDialog extends FloatingDialog{ float offsetX = panX + width/2f + x, offsetY = panY + height/2f + y; for(TechTreeNode node : nodes){ + if(!node.visible) continue; for(TechTreeNode child : node.children){ - Lines.stroke(Unit.dp.scl(3f), locked(node.node) || locked(child.node) ? Pal.locked : Pal.accent); + if(!child.visible) continue; + Lines.stroke(Unit.dp.scl(3f), locked(node.node) || locked(child.node) ? Pal.locked : Pal.accent); Lines.line(node.x + offsetX, node.y + offsetY, child.x + offsetX, child.y + offsetY); } } diff --git a/core/src/io/anuke/mindustry/ui/fragments/BlockConfigFragment.java b/core/src/io/anuke/mindustry/ui/fragments/BlockConfigFragment.java index 6617701231..4dc0efa263 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/BlockConfigFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/BlockConfigFragment.java @@ -29,6 +29,7 @@ public class BlockConfigFragment extends Fragment{ @Override public void build(Group parent){ + table.visible(false); parent.addChild(table); } diff --git a/core/src/io/anuke/mindustry/ui/fragments/BlockInventoryFragment.java b/core/src/io/anuke/mindustry/ui/fragments/BlockInventoryFragment.java index 039d5f1152..4d65d33136 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/BlockInventoryFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/BlockInventoryFragment.java @@ -66,6 +66,10 @@ public class BlockInventoryFragment extends Fragment{ } public void showFor(Tile t){ + if(this.tile == t.target()){ + hide(); + return; + } this.tile = t.target(); if(tile == null || tile.entity == null || !tile.block().isAccessible() || tile.entity.items.total() == 0) return; diff --git a/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java b/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java index 8070ccaab5..682fabf56e 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java @@ -21,6 +21,7 @@ import io.anuke.arc.util.Scaling; import io.anuke.arc.util.Time; import io.anuke.arc.util.Tmp; import io.anuke.mindustry.core.GameState.State; +import io.anuke.mindustry.game.EventType.PlayEvent; import io.anuke.mindustry.game.EventType.StateChangeEvent; import io.anuke.mindustry.game.UnlockableContent; import io.anuke.mindustry.gen.Call; @@ -46,6 +47,16 @@ public class HudFragment extends Fragment{ private float coreAttackTime; private float lastCoreHP; private float coreAttackOpacity = 0f; + private Table goshDarnHeckingFlippedTableWhyDoesThisHappen; + + { + Events.on(PlayEvent.class, event -> { + if(goshDarnHeckingFlippedTableWhyDoesThisHappen != null){ + goshDarnHeckingFlippedTableWhyDoesThisHappen.invalidateHierarchy(); + goshDarnHeckingFlippedTableWhyDoesThisHappen.pack(); + } + }); + } public void build(Group parent){ @@ -55,6 +66,7 @@ public class HudFragment extends Fragment{ if(mobile){ cont.table(select -> { + goshDarnHeckingFlippedTableWhyDoesThisHappen = select; select.left(); select.defaults().size(dsize).left(); @@ -124,7 +136,7 @@ public class HudFragment extends Fragment{ stuff.add(stack).width(dsize * 4 + 3f); stuff.row(); stuff.table("button", t -> t.margin(10f).add(new Bar("boss.health", Pal.health, () -> state.boss() == null ? 0f : state.boss().healthf()).blink(Color.WHITE)) - .grow()).fillX().visible(() -> world.isZone() && state.boss() != null).height(60f).get(); + .grow()).fillX().visible(() -> state.rules.waves && state.boss() != null).height(60f).get(); stuff.row(); }).visible(() -> shown); }); @@ -132,7 +144,7 @@ public class HudFragment extends Fragment{ //fps display parent.fill(info -> { - info.top().right().margin(4).visible(() -> Core.settings.getBool("fps")); + info.top().right().margin(4).visible(() -> Core.settings.getBool("fps") && !state.is(State.menu)); IntFormat fps = new IntFormat("fps"); IntFormat ping = new IntFormat("ping"); info.label(() -> fps.get(Core.graphics.getFramesPerSecond())).right(); diff --git a/core/src/io/anuke/mindustry/ui/fragments/MenuFragment.java b/core/src/io/anuke/mindustry/ui/fragments/MenuFragment.java index 5e721f9d45..09671c6f7c 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/MenuFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/MenuFragment.java @@ -43,7 +43,7 @@ public class MenuFragment extends Fragment{ } //version info - parent.fill(c -> c.bottom().left().add(Strings.formatArgs("Mindustry v{0} {1}-{2} {3}{4}", Version.number, Version.modifier, Version.type, + parent.fill(c -> c.bottom().left().add(Strings.format("Mindustry v{0} {1}-{2} {3}{4}", Version.number, Version.modifier, Version.type, (Version.build == -1 ? "custom build" : "build " + Version.build), Version.revision == 0 ? "" : "." + Version.revision)) .visible(() -> state.is(State.menu))); } @@ -138,7 +138,7 @@ public class MenuFragment extends Fragment{ FloatingDialog dialog = new FloatingDialog("$play"); dialog.setFillParent(false); dialog.addCloseButton(); - dialog.cont.defaults().size(230f, 64f); + dialog.cont.defaults().size(210f, 64f); dialog.cont.add(new MenuButton("icon-editor", "$newgame", () -> { dialog.hide(); ui.custom.show(); diff --git a/core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java b/core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java index b4c93d4195..2a05fe64f0 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java @@ -13,6 +13,7 @@ import io.anuke.arc.scene.ui.ButtonGroup; import io.anuke.arc.scene.ui.Image; import io.anuke.arc.scene.ui.ImageButton; import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.mindustry.content.Blocks; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.game.EventType.UnlockEvent; @@ -26,7 +27,6 @@ import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Block.Icon; import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.blocks.OreBlock; import static io.anuke.mindustry.Vars.*; @@ -340,6 +340,6 @@ public class PlacementFragment extends Fragment{ /** Returns the block currently being hovered over in the world. */ Block tileDisplayBlock(){ - return hoverTile == null ? null : hoverTile.block().synthetic() ? hoverTile.block() : hoverTile.floor() instanceof OreBlock ? hoverTile.floor() : null; + return hoverTile == null ? null : hoverTile.block().synthetic() ? hoverTile.block() : hoverTile.ore() != Blocks.air ? hoverTile.ore() : null; } } \ No newline at end of file diff --git a/core/src/io/anuke/mindustry/world/Block.java b/core/src/io/anuke/mindustry/world/Block.java index 749e26f756..95bfcb99eb 100644 --- a/core/src/io/anuke/mindustry/world/Block.java +++ b/core/src/io/anuke/mindustry/world/Block.java @@ -8,14 +8,13 @@ import io.anuke.arc.collection.EnumSet; import io.anuke.arc.function.BooleanProvider; import io.anuke.arc.function.Function; import io.anuke.arc.graphics.Color; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.graphics.g2d.Lines; -import io.anuke.arc.graphics.g2d.TextureRegion; +import io.anuke.arc.graphics.g2d.*; +import io.anuke.arc.graphics.g2d.TextureAtlas.AtlasRegion; import io.anuke.arc.math.Mathf; import io.anuke.arc.scene.ui.layout.Table; -import io.anuke.arc.util.Log; -import io.anuke.arc.util.Strings; +import io.anuke.arc.util.Align; import io.anuke.arc.util.Time; +import io.anuke.arc.util.pooling.Pools; import io.anuke.mindustry.entities.Damage; import io.anuke.mindustry.entities.bullet.Bullet; import io.anuke.mindustry.entities.effect.Puddle; @@ -33,10 +32,7 @@ import io.anuke.mindustry.ui.ContentDisplay; import io.anuke.mindustry.world.consumers.Consume; import io.anuke.mindustry.world.consumers.ConsumeLiquid; import io.anuke.mindustry.world.consumers.ConsumePower; -import io.anuke.mindustry.world.meta.BlockFlag; -import io.anuke.mindustry.world.meta.BlockGroup; -import io.anuke.mindustry.world.meta.BlockStat; -import io.anuke.mindustry.world.meta.StatUnit; +import io.anuke.mindustry.world.meta.*; import java.util.Arrays; @@ -112,8 +108,8 @@ public class Block extends BlockStorage{ protected Array tempTiles = new Array<>(); protected TextureRegion[] icons = new TextureRegion[Icon.values().length]; protected TextureRegion[] generatedIcons; - protected TextureRegion[] variantRegions; - protected TextureRegion region; + protected TextureRegion[] variantRegions, editorVariantRegions; + protected TextureRegion region, editorIcon; public Block(String name){ super(name); @@ -157,6 +153,8 @@ public class Block extends BlockStorage{ public Array getPowerConnections(Tile tile, Array out){ out.clear(); + if(tile == null || tile.entity == null || tile.entity.power == null) return out; + for(Tile other : tile.entity.proximity()){ if(other.entity.power != null && !(consumesPower && other.block().consumesPower && !outputsPower && !other.block().outputsPower) && !tile.entity.power.links.contains(other.pos())){ @@ -201,6 +199,28 @@ public class Block extends BlockStorage{ public void drawPlace(int x, int y, int rotation, boolean valid){ } + protected void drawPlaceText(String text, int x, int y, boolean valid){ + Color color = valid ? Pal.accent : Pal.remove; + BitmapFont font = Core.scene.skin.getFont("default-font"); + GlyphLayout layout = Pools.obtain(GlyphLayout.class, GlyphLayout::new); + boolean ints = font.usesIntegerPositions(); + font.setUseIntegerPositions(false); + font.getData().setScale(1f / 4f); + layout.setText(font, text); + + font.setColor(color); + float dx = x*tilesize + offset(), dy = y*tilesize + offset() + size*tilesize/2f + 2; + font.draw(text, dx, dy + layout.height + 1, Align.center); + Lines.stroke(1f, color); + Lines.line(dx - layout.width/2f - 2f, dy, dx + layout.width/2f + 2f, dy); + + font.setUseIntegerPositions(ints); + font.setColor(Color.WHITE); + font.getData().setScale(1f); + Draw.reset(); + Pools.free(layout); + } + public void draw(Tile tile){ Draw.rect(region, tile.drawx(), tile.drawy(), rotate ? tile.getRotation() * 90 : 0); } @@ -247,6 +267,15 @@ public class Block extends BlockStorage{ } } + public float sumAttribute(Attribute attr, int x, int y){ + Tile tile = world.tile(x, y); + float sum = 0; + for(Tile other : tile.getLinkedTilesAs(this, tempTiles)){ + sum += other.floor().attributes.get(attr); + } + return sum; + } + @Override public String localizedName(){ return localizedName; @@ -284,10 +313,6 @@ public class Block extends BlockStorage{ setBars(); consumes.checkRequired(this); - - if(buildRequirements.length > 0 && !Core.bundle.has("block." + name + ".name")){ - Log.warn("No name for block '{0}' found. Add the following to bundle.properties:\nblock.{0}.name = {1}", name, Strings.capitalize(name)); - } } @Override @@ -367,7 +392,15 @@ public class Block extends BlockStorage{ } if(hasPower && consumes.has(ConsumePower.class)){ - bars.add("power", entity -> new Bar(consumes.get(ConsumePower.class).isBuffered ? "blocks.power" : "blocks.power.satisfaction", Pal.powerBar, () -> entity.power.satisfaction)); + boolean buffered = consumes.get(ConsumePower.class).isBuffered; + float capacity = consumes.get(ConsumePower.class).powerCapacity; + + bars.add("power", entity -> new Bar(() -> buffered ? Core.bundle.format("blocks.powerbalance", Float.isNaN(entity.power.satisfaction * capacity) ? "" : (int)(entity.power.satisfaction * capacity)) : + Core.bundle.get("blocks.power"), () -> Pal.powerBar, () -> entity.power.satisfaction)); + } + + if(hasItems && configurable){ + bars.add("items", entity -> new Bar(() -> Core.bundle.format("blocks.items", entity.items.total()), () -> Pal.items, () -> (float)entity.items.total() / itemCapacity)); } } @@ -513,6 +546,25 @@ public class Block extends BlockStorage{ return icons[icon.ordinal()]; } + /**Never use outside of the editor!*/ + public TextureRegion editorIcon(){ + if(editorIcon == null) editorIcon = Core.atlas.find(name + "-icon-editor"); + return editorIcon; + } + + /**Never use outside of the editor!*/ + public TextureRegion[] editorVariantRegions(){ + if(editorVariantRegions == null){ + variantRegions(); + editorVariantRegions = new TextureRegion[variantRegions.length]; + for(int i = 0; i < variantRegions.length; i ++){ + AtlasRegion region = (AtlasRegion)variantRegions[i]; + editorVariantRegions[i] = Core.atlas.find("editor-" + region.name); + } + } + return editorVariantRegions; + } + protected TextureRegion[] generateIcons(){ return new TextureRegion[]{Core.atlas.find(name)}; } diff --git a/core/src/io/anuke/mindustry/world/Build.java b/core/src/io/anuke/mindustry/world/Build.java index cb7785e980..9d77ee82f5 100644 --- a/core/src/io/anuke/mindustry/world/Build.java +++ b/core/src/io/anuke/mindustry/world/Build.java @@ -31,7 +31,7 @@ public class Build{ if(tile == null) return; if(tile.entity != null){ - prevPercent = tile.entity.health(); + prevPercent = tile.entity.healthf(); } tile = tile.target(); diff --git a/core/src/io/anuke/mindustry/world/CachedTile.java b/core/src/io/anuke/mindustry/world/CachedTile.java new file mode 100644 index 0000000000..6672bb6d2f --- /dev/null +++ b/core/src/io/anuke/mindustry/world/CachedTile.java @@ -0,0 +1,51 @@ +package io.anuke.mindustry.world; + +import io.anuke.arc.collection.IntMap; +import io.anuke.mindustry.entities.type.TileEntity; +import io.anuke.mindustry.game.Team; +import io.anuke.mindustry.world.modules.ConsumeModule; +import io.anuke.mindustry.world.modules.ItemModule; +import io.anuke.mindustry.world.modules.LiquidModule; +import io.anuke.mindustry.world.modules.PowerModule; + +/**A tile which does not trigger change events and whose entity types are cached. + * Prevents garbage when loading previews.*/ +public class CachedTile extends Tile{ + private static IntMap entities = new IntMap<>(); + + public CachedTile(){ + super(0, 0); + } + + @Override + public Team getTeam(){ + return Team.all[getTeamID()]; + } + + @Override + protected void preChanged(){ + super.setTeam(Team.none); + } + + @Override + protected void changed(){ + entity = null; + + Block block = block(); + + if(block.hasEntity()){ + //cache all entity types so only one is ever created per block type. do not add it. + if(!entities.containsKey(block.id)){ + TileEntity n = block.newEntity(); + n.cons = new ConsumeModule(entity); + if(block.hasItems) n.items = new ItemModule(); + if(block.hasLiquids) n.liquids = new LiquidModule(); + if(block.hasPower) n.power = new PowerModule(); + entities.put(block.id, n); + } + + entity = entities.get(block.id); + + } + } +} diff --git a/core/src/io/anuke/mindustry/world/LegacyColorMapper.java b/core/src/io/anuke/mindustry/world/LegacyColorMapper.java index 2edadf36c7..2879f7d894 100644 --- a/core/src/io/anuke/mindustry/world/LegacyColorMapper.java +++ b/core/src/io/anuke/mindustry/world/LegacyColorMapper.java @@ -3,10 +3,8 @@ package io.anuke.mindustry.world; import io.anuke.arc.collection.IntMap; import io.anuke.arc.graphics.Color; import io.anuke.mindustry.content.Blocks; -import io.anuke.mindustry.content.Items; import io.anuke.mindustry.game.ContentList; import io.anuke.mindustry.world.blocks.Floor; -import io.anuke.mindustry.world.blocks.OreBlock; public class LegacyColorMapper implements ContentList{ private static IntMap blockMap = new IntMap<>(); @@ -20,12 +18,12 @@ public class LegacyColorMapper implements ContentList{ public void load(){ defaultValue = new LegacyBlock(Blocks.stone, Blocks.air); - map("ff0000", Blocks.stainedStone, Blocks.spawn); + map("ff0000", Blocks.stone, Blocks.spawn); map("00ff00", Blocks.stone); map("323232", Blocks.stone); map("646464", Blocks.stone, Blocks.rocks); - map("50965a", Blocks.stainedStone); - map("5ab464", Blocks.stainedStone, Blocks.stainedRocks); + map("50965a", Blocks.grass); + map("5ab464", Blocks.grass, Blocks.pine); map("506eb4", Blocks.water); map("465a96", Blocks.deepwater); map("252525", Blocks.ignarock); @@ -35,13 +33,17 @@ public class LegacyColorMapper implements ContentList{ map("c2d1d2", Blocks.snow); map("c4e3e7", Blocks.ice); map("f7feff", Blocks.snow, Blocks.snowrocks); - map("6e501e", Blocks.stainedStone); - map("ed5334", Blocks.stainedStoneRed); + map("6e501e", Blocks.holostone); + map("ed5334", Blocks.magmarock); map("292929", Blocks.tar); - map("c3a490", OreBlock.get(Blocks.stone, Items.copper)); - map("161616", OreBlock.get(Blocks.stone, Items.coal)); - map("6277bc", OreBlock.get(Blocks.stone, Items.titanium)); - map("83bc58", OreBlock.get(Blocks.stone, Items.thorium)); + map("c3a490", Blocks.stone, Blocks.air, Blocks.oreCopper); + map("161616", Blocks.stone, Blocks.air, Blocks.oreCoal); + map("6277bc", Blocks.stone, Blocks.air, Blocks.oreTitanium); + map("83bc58", Blocks.stone, Blocks.air, Blocks.oreThorium); + } + + private void map(String color, Block block, Block wall, Block ore){ + blockMap.put(Color.rgba8888(Color.valueOf(color)), new LegacyBlock(block, wall, ore)); } private void map(String color, Block block, Block wall){ @@ -55,10 +57,18 @@ public class LegacyColorMapper implements ContentList{ public static class LegacyBlock{ public final Floor floor; public final Block wall; + public final Block ore; public LegacyBlock(Block floor, Block wall){ this.floor = (Floor) floor; this.wall = wall; + this.ore = null; + } + + public LegacyBlock(Block floor, Block wall, Block ore){ + this.floor = (Floor) floor; + this.wall = wall; + this.ore = ore; } } diff --git a/core/src/io/anuke/mindustry/world/Tile.java b/core/src/io/anuke/mindustry/world/Tile.java index 5bc7e46926..bb3d9dacfa 100644 --- a/core/src/io/anuke/mindustry/world/Tile.java +++ b/core/src/io/anuke/mindustry/world/Tile.java @@ -9,9 +9,10 @@ import io.anuke.arc.math.geom.Position; import io.anuke.arc.math.geom.Vector2; import io.anuke.arc.util.Pack; import io.anuke.mindustry.content.Blocks; -import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.entities.traits.TargetTrait; +import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.game.Team; +import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.blocks.BlockPart; import io.anuke.mindustry.world.blocks.Floor; import io.anuke.mindustry.world.modules.ConsumeModule; @@ -39,10 +40,13 @@ public class Tile implements Position, TargetTrait{ private byte rotation; /** Team ordinal. */ private byte team; + /**Ore that is on top of this (floor) block.*/ + private byte ore = 0; public Tile(int x, int y){ this.x = (short) x; this.y = (short) y; + wall = floor = (Floor)Blocks.air; } public Tile(int x, int y, byte floor, byte wall){ @@ -159,6 +163,7 @@ public class Tile implements Position, TargetTrait{ public void setFloor(Floor type){ this.floor = type; + this.ore = 0; } public byte getRotation(){ @@ -213,6 +218,14 @@ public class Tile implements Position, TargetTrait{ return link != 0; } + public byte getLinkByte(){ + return link; + } + + public void setLinkByte(byte b){ + this.link = b; + } + /** Sets this to a linked tile, which sets the block to a part. dx and dy can only be -8-7. */ public void setLinked(byte dx, byte dy){ setBlock(Blocks.part); @@ -316,6 +329,30 @@ public class Tile implements Position, TargetTrait{ return getTeam() == Team.none || team == getTeam(); } + public byte getOreByte(){ + return ore; + } + + public void setOreByte(byte ore){ + this.ore = ore; + } + + public void setOre(Block block){ + setOreByte(block.id); + } + + public void clearOre(){ + this.ore = 0; + } + + public Floor ore(){ + return (Floor)content.block(ore); + } + + public Item drop(){ + return ore == 0 ? floor.itemDrop : ((Floor)content.block(ore)).itemDrop; + } + public void updateOcclusion(){ cost = 1; boolean occluded = false; @@ -343,7 +380,7 @@ public class Tile implements Position, TargetTrait{ } } - private void preChanged(){ + protected void preChanged(){ block().removed(this); if(entity != null){ entity.removeFromProximity(); @@ -351,7 +388,7 @@ public class Tile implements Position, TargetTrait{ team = 0; } - private void changed(){ + protected void changed(){ if(entity != null){ entity.remove(); entity = null; diff --git a/core/src/io/anuke/mindustry/world/blocks/Attributes.java b/core/src/io/anuke/mindustry/world/blocks/Attributes.java new file mode 100644 index 0000000000..ce343a852c --- /dev/null +++ b/core/src/io/anuke/mindustry/world/blocks/Attributes.java @@ -0,0 +1,15 @@ +package io.anuke.mindustry.world.blocks; + +import io.anuke.mindustry.world.meta.Attribute; + +public class Attributes{ + private float[] array = new float[Attribute.values().length]; + + public float get(Attribute attr){ + return array[attr.ordinal()]; + } + + public void set(Attribute attr, float value){ + array[attr.ordinal()] = value; + } +} diff --git a/core/src/io/anuke/mindustry/world/blocks/BlockPart.java b/core/src/io/anuke/mindustry/world/blocks/BlockPart.java index 50ae9a08db..512b39df20 100644 --- a/core/src/io/anuke/mindustry/world/blocks/BlockPart.java +++ b/core/src/io/anuke/mindustry/world/blocks/BlockPart.java @@ -18,6 +18,16 @@ public class BlockPart extends Block{ hasPower = hasItems = hasLiquids = true; } + @Override + public void drawTeam(Tile tile){ + + } + + @Override + public boolean synthetic(){ + return true; + } + @Override public boolean isHidden(){ return true; diff --git a/core/src/io/anuke/mindustry/world/blocks/BuildBlock.java b/core/src/io/anuke/mindustry/world/blocks/BuildBlock.java index 2eaba1415a..f81fb7859e 100644 --- a/core/src/io/anuke/mindustry/world/blocks/BuildBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/BuildBlock.java @@ -56,8 +56,12 @@ public class BuildBlock extends Block{ @Remote(called = Loc.server) public static void onConstructFinish(Tile tile, Block block, int builderID, byte rotation, Team team){ if(tile == null) return; + float healthf = tile.entity == null ? 1f : tile.entity.healthf(); tile.setRotation(rotation); world.setBlock(tile, block, team); + if(tile.entity != null){ + tile.entity.health = block.health * healthf; + } Effects.effect(Fx.placeBlock, tile.drawx(), tile.drawy(), block.size); Core.app.post(() -> tile.block().placed(tile)); @@ -186,7 +190,7 @@ public class BuildBlock extends Block{ public void construct(Unit builder, TileEntity core, float amount){ if(block == null){ - damage(99999); + kill(); return; } diff --git a/core/src/io/anuke/mindustry/world/blocks/Floor.java b/core/src/io/anuke/mindustry/world/blocks/Floor.java index a7f4430371..0487c66e85 100644 --- a/core/src/io/anuke/mindustry/world/blocks/Floor.java +++ b/core/src/io/anuke/mindustry/world/blocks/Floor.java @@ -7,6 +7,7 @@ import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Geometry; import io.anuke.arc.math.geom.Point2; +import io.anuke.mindustry.content.Blocks; import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.content.StatusEffects; import io.anuke.mindustry.entities.Effects.Effect; @@ -45,12 +46,8 @@ public class Floor extends Block{ public Liquid liquidDrop = null; /** item that drops from this block, used for drills */ public Item itemDrop = null; - /** Whether ores generate on this block. */ - public boolean hasOres = false; /** whether this block can be drowned in */ public boolean isLiquid; - /** Heat of this block, 0 at baseline. Used for calculating output of thermal generators.*/ - public float heat = 0f; /** if true, this block cannot be mined by players. useful for annoying things like sand. */ public boolean playerUnmineable = false; /**Style of the edge stencil. Loaded by looking up "edge-stencil-{name}".*/ @@ -59,6 +56,8 @@ public class Floor extends Block{ public Block blendGroup = this; /**Effect displayed when randomly updated.*/ public Effect updateEffect = Fx.none; + /**Array of affinities to certain things.*/ + public Attributes attributes = new Attributes(); protected TextureRegion[][] edges; protected byte eq = 0; @@ -110,17 +109,32 @@ public class Floor extends Block{ Mathf.random.setSeed(tile.pos()); Draw.rect(variantRegions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, variantRegions.length - 1))], tile.worldx(), tile.worldy()); + Floor floor = tile.ore(); + if(floor != Blocks.air && floor != this){ //ore should never have itself on top, but it's possible, so prevent a crash in that case + floor.draw(tile); + } drawEdges(tile); } + + public void drawNonLayer(Tile tile){ + Mathf.random.setSeed(tile.pos()); + + drawEdges(tile, true); + } + protected void drawEdges(Tile tile){ + drawEdges(tile, false); + } + + protected void drawEdges(Tile tile, boolean sameLayer){ eq = 0; for(int i = 0; i < 8; i++){ Point2 point = Geometry.d8[i]; Tile other = tile.getNearby(point); - if(other != null && doEdge(other.floor()) && other.floor().edges() != null){ + if(other != null && doEdge(other.floor(), sameLayer) && other.floor().edges() != null){ eq |= (1 << i); } } @@ -140,8 +154,8 @@ public class Floor extends Block{ return ((Floor)blendGroup).edges; } - protected boolean doEdge(Floor other){ - return (other.blendGroup.id > blendGroup.id || edges() == null) && other.edgeOnto(this); + protected boolean doEdge(Floor other, boolean sameLayer){ + return (other.blendGroup.id > blendGroup.id || edges() == null) && other.edgeOnto(this) && (other.cacheLayer.ordinal() > this.cacheLayer.ordinal() || !sameLayer); } protected boolean edgeOnto(Floor other){ diff --git a/core/src/io/anuke/mindustry/world/blocks/OreBlock.java b/core/src/io/anuke/mindustry/world/blocks/OreBlock.java index 97c7dec8a9..d8ba5b6435 100644 --- a/core/src/io/anuke/mindustry/world/blocks/OreBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/OreBlock.java @@ -1,28 +1,18 @@ package io.anuke.mindustry.world.blocks; -import io.anuke.arc.collection.ObjectMap; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.math.Mathf; import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; public class OreBlock extends Floor{ - private static final ObjectMap> oreBlockMap = new ObjectMap<>(); - public Floor base; - - public OreBlock(Item ore, Floor base){ - super("ore-" + ore.name + "-" + base.name); - this.localizedName = ore.localizedName() + " " + base.localizedName; + public OreBlock(Item ore){ + super("ore-" + ore.name); + this.localizedName = ore.localizedName(); this.itemDrop = ore; - this.base = base; this.variants = 3; - this.edge = base.name; - this.blendGroup = base.blendGroup; this.color.set(ore.color); - - oreBlockMap.getOr(ore, ObjectMap::new).put(base, this); } @Override @@ -38,22 +28,5 @@ public class OreBlock extends Floor{ @Override public void draw(Tile tile){ Draw.rect(variantRegions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, variantRegions.length - 1))], tile.worldx(), tile.worldy()); - - drawEdges(tile); - } - - @Override - public boolean doEdge(Floor floor){ - return floor != base && super.doEdge(floor); - } - - @Override - protected boolean edgeOnto(Floor other){ - return other != base; - } - - public static Floor get(Block floor, Item item){ - if(!oreBlockMap.containsKey(item) || !oreBlockMap.get(item).containsKey(floor)) return null; - return oreBlockMap.get(item).get(floor); } } diff --git a/core/src/io/anuke/mindustry/world/blocks/Rock.java b/core/src/io/anuke/mindustry/world/blocks/Rock.java index e73652d1c3..7f10510e96 100644 --- a/core/src/io/anuke/mindustry/world/blocks/Rock.java +++ b/core/src/io/anuke/mindustry/world/blocks/Rock.java @@ -8,7 +8,6 @@ import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.math.Mathf; public class Rock extends Block{ - protected TextureRegion[] regions; protected int variants; public Rock(String name){ @@ -20,17 +19,12 @@ public class Rock extends Block{ @Override public void draw(Tile tile){ if(variants > 0){ - Draw.rect(regions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, regions.length - 1))], tile.worldx(), tile.worldy()); + Draw.rect(variantRegions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, variantRegions.length - 1))], tile.worldx(), tile.worldy()); }else{ Draw.rect(region, tile.worldx(), tile.worldy()); } } - @Override - public TextureRegion[] variantRegions(){ - return regions; - } - @Override public TextureRegion[] generateIcons(){ return variants == 0 ? super.generateIcons() : new TextureRegion[]{Core.atlas.find(name + "1")}; @@ -41,10 +35,10 @@ public class Rock extends Block{ super.load(); if(variants > 0){ - regions = new TextureRegion[variants]; + variantRegions = new TextureRegion[variants]; for(int i = 0; i < variants; i++){ - regions[i] = Core.atlas.find(name + (i + 1)); + variantRegions[i] = Core.atlas.find(name + (i + 1)); } } } diff --git a/core/src/io/anuke/mindustry/world/blocks/StaticWall.java b/core/src/io/anuke/mindustry/world/blocks/StaticWall.java index af2f6e29aa..cc2d73ce0b 100644 --- a/core/src/io/anuke/mindustry/world/blocks/StaticWall.java +++ b/core/src/io/anuke/mindustry/world/blocks/StaticWall.java @@ -31,7 +31,7 @@ public class StaticWall extends Rock{ Draw.rect(large, tile.worldx() + tilesize/2f, tile.worldy() + tilesize/2f); } }else if(variants > 0){ - Draw.rect(regions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, regions.length - 1))], tile.worldx(), tile.worldy()); + Draw.rect(variantRegions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, variantRegions.length - 1))], tile.worldx(), tile.worldy()); }else{ Draw.rect(region, tile.worldx(), tile.worldy()); } diff --git a/core/src/io/anuke/mindustry/world/blocks/distribution/Conveyor.java b/core/src/io/anuke/mindustry/world/blocks/distribution/Conveyor.java index ff8f0b0662..3858b02e48 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/Conveyor.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/Conveyor.java @@ -182,7 +182,7 @@ public class Conveyor extends Block{ entity.minitem = 1f; Tile next = tile.getNearby(tile.getRotation()); - float nextMax = next.block() instanceof Conveyor ? 1f - Math.max(itemSpace - next.entity().minitem, 0) : 1f; + float nextMax = next != null && next.block() instanceof Conveyor ? 1f - Math.max(itemSpace - next.entity().minitem, 0) : 1f; int minremove = Integer.MAX_VALUE; for(int i = entity.convey.size - 1; i >= 0; i--){ diff --git a/core/src/io/anuke/mindustry/world/blocks/distribution/ItemBridge.java b/core/src/io/anuke/mindustry/world/blocks/distribution/ItemBridge.java index b3b7ffc1d7..20be93efda 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/ItemBridge.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/ItemBridge.java @@ -91,7 +91,7 @@ public class ItemBridge extends Block{ } public Tile findLink(int x, int y){ - if(linkValid(world.tile(x, y), world.tile(lastPlaced)) && lastPlaced != Pos.get(x, y)){ + if(world.tile(x, y) != null && linkValid(world.tile(x, y), world.tile(lastPlaced)) && lastPlaced != Pos.get(x, y)){ return world.tile(lastPlaced); } @@ -312,7 +312,7 @@ public class ItemBridge extends Block{ } public boolean linkValid(Tile tile, Tile other, boolean checkDouble){ - if(other == null) return false; + if(other == null || tile == null) return false; if(tile.x == other.x){ if(Math.abs(tile.y - other.y) > range) return false; }else if(tile.y == other.y){ diff --git a/core/src/io/anuke/mindustry/world/blocks/distribution/LiquidJunction.java b/core/src/io/anuke/mindustry/world/blocks/distribution/LiquidJunction.java index 49ab325cd2..7dfd439bc6 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/LiquidJunction.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/LiquidJunction.java @@ -21,6 +21,12 @@ public class LiquidJunction extends LiquidBlock{ stats.remove(BlockStat.liquidCapacity); } + @Override + public void setBars(){ + super.setBars(); + bars.remove("liquid"); + } + @Override public void draw(Tile tile){ Draw.rect(name, tile.worldx(), tile.worldy()); diff --git a/core/src/io/anuke/mindustry/world/blocks/distribution/MassDriver.java b/core/src/io/anuke/mindustry/world/blocks/distribution/MassDriver.java index 01d1f3f740..37c059464a 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/MassDriver.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/MassDriver.java @@ -111,7 +111,7 @@ public class MassDriver extends Block{ @Override public TextureRegion[] generateIcons(){ - return new TextureRegion[]{Core.atlas.find(name + "-base"), Core.atlas.find(name + "-turret")}; + return new TextureRegion[]{Core.atlas.find(name + "-base"), Core.atlas.find(name)}; } @Override diff --git a/core/src/io/anuke/mindustry/world/blocks/power/ImpactReactor.java b/core/src/io/anuke/mindustry/world/blocks/power/ImpactReactor.java index f98e8219d2..9a18a8fe4f 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/ImpactReactor.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/ImpactReactor.java @@ -52,7 +52,7 @@ public class ImpactReactor extends PowerGenerator{ bars.add("poweroutput", entity -> new Bar(() -> Core.bundle.format("blocks.poweroutput", - Strings.toFixed(Math.max(entity.tile.block().getPowerProduction(entity.tile) - consumes.get(ConsumePower.class).powerPerTick, 0)*60, 1)), + Strings.toFixed(Math.max(entity.tile.block().getPowerProduction(entity.tile) - consumes.get(ConsumePower.class).powerPerTick, 0)*60 * entity.delta(), 1)), () -> Pal.powerBar, () -> ((GeneratorEntity)entity).productionEfficiency)); } diff --git a/core/src/io/anuke/mindustry/world/blocks/power/PowerDistributor.java b/core/src/io/anuke/mindustry/world/blocks/power/PowerDistributor.java index d7011f7261..5a4bbfcdce 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/PowerDistributor.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/PowerDistributor.java @@ -13,6 +13,8 @@ public class PowerDistributor extends PowerBlock{ @Override public void update(Tile tile){ - tile.entity.power.graph.update(); + if(tile.entity != null && tile.entity.power != null && tile.entity.power.graph != null){ + tile.entity.power.graph.update(); + } } } diff --git a/core/src/io/anuke/mindustry/world/blocks/power/PowerGraph.java b/core/src/io/anuke/mindustry/world/blocks/power/PowerGraph.java index e01eb0294c..949a549c89 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/PowerGraph.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/PowerGraph.java @@ -106,7 +106,7 @@ public class PowerGraph{ public float chargeBatteries(float excess){ float capacity = getBatteryCapacity(); - if(Mathf.isEqual(capacity, 0f)){ return 0f; } + if(Mathf.isEqual(capacity, 0f)) return 0f; for(Tile battery : batteries){ Consumers consumes = battery.block().consumes; @@ -123,16 +123,18 @@ public class PowerGraph{ public void distributePower(float needed, float produced){ //distribute even if not needed. this is because some might be requiring power but not requesting it; it updates consumers - float coverage = Math.min(1, produced / needed); + float coverage = Mathf.isZero(needed) ? 1f : Math.min(1, produced / needed); for(Tile consumer : consumers){ Consumers consumes = consumer.block().consumes; if(consumes.has(ConsumePower.class)){ ConsumePower consumePower = consumes.get(ConsumePower.class); //currently satisfies power even if it's not required yet if(consumePower.isBuffered){ - // Add an equal percentage of power to all buffers, based on the global power coverage in this graph - float maximumRate = consumePower.requestedPower(consumer.block(), consumer.entity()) * coverage * consumer.entity.delta(); - consumer.entity.power.satisfaction = Mathf.clamp(consumer.entity.power.satisfaction + maximumRate / consumePower.powerCapacity); + if(!Mathf.isZero(consumePower.powerCapacity)){ + // Add an equal percentage of power to all buffers, based on the global power coverage in this graph + float maximumRate = consumePower.requestedPower(consumer.block(), consumer.entity()) * coverage * consumer.entity.delta(); + consumer.entity.power.satisfaction = Mathf.clamp(consumer.entity.power.satisfaction + maximumRate / consumePower.powerCapacity); + } }else{ consumer.entity.power.satisfaction = coverage; } @@ -141,10 +143,6 @@ public class PowerGraph{ } public void update(){ - if(Core.graphics.getFrameId() == lastFrameUpdated || (consumers.size == 0 && producers.size == 0 && batteries.size == 0)){ - return; - } - lastFrameUpdated = Core.graphics.getFrameId(); float powerNeeded = getPowerNeeded(); @@ -152,6 +150,10 @@ public class PowerGraph{ powerBalance.addValue((powerProduced - powerNeeded) / Time.delta()); + if(Core.graphics.getFrameId() == lastFrameUpdated || (consumers.size == 0 && producers.size == 0 && batteries.size == 0)){ + return; + } + if(!Mathf.isEqual(powerNeeded, powerProduced)){ if(powerNeeded > powerProduced){ powerProduced += useBatteries(powerNeeded - powerProduced); diff --git a/core/src/io/anuke/mindustry/world/blocks/power/ThermalGenerator.java b/core/src/io/anuke/mindustry/world/blocks/power/ThermalGenerator.java index b0f79b0035..053840decf 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/ThermalGenerator.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/ThermalGenerator.java @@ -1,10 +1,12 @@ package io.anuke.mindustry.world.blocks.power; -import io.anuke.mindustry.entities.Effects; -import io.anuke.mindustry.entities.Effects.Effect; +import io.anuke.arc.Core; import io.anuke.arc.math.Mathf; import io.anuke.mindustry.content.Fx; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.Effects.Effect; import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.meta.Attribute; public class ThermalGenerator extends PowerGenerator{ protected Effect generateEffect = Fx.none; @@ -24,6 +26,11 @@ public class ThermalGenerator extends PowerGenerator{ super.update(tile); } + @Override + public void drawPlace(int x, int y, int rotation, boolean valid){ + drawPlaceText(Core.bundle.format("blocks.efficiency", sumAttribute(Attribute.heat, x, y)*100, 1), x, y, valid); + } + @Override public void placed(Tile tile){ super.placed(tile); @@ -34,10 +41,7 @@ public class ThermalGenerator extends PowerGenerator{ super.onProximityAdded(tile); GeneratorEntity entity = tile.entity(); - entity.productionEfficiency = 0f; - for(Tile other : tile.getLinkedTiles(tempTiles)){ - entity.productionEfficiency += other.floor().heat; - } + entity.productionEfficiency = sumAttribute(Attribute.heat, tile.x, tile.y); } @Override @@ -50,6 +54,6 @@ public class ThermalGenerator extends PowerGenerator{ @Override public boolean canPlaceOn(Tile tile){ //make sure there's heat at this location - return tile.getLinkedTilesAs(this, tempTiles).sum(other -> other.floor().heat) > 0.01f; + return tile.getLinkedTilesAs(this, tempTiles).sum(other -> other.floor().attributes.get(Attribute.heat)) > 0.01f; } } diff --git a/core/src/io/anuke/mindustry/world/blocks/production/Cultivator.java b/core/src/io/anuke/mindustry/world/blocks/production/Cultivator.java index 6a5ac51af7..51cf6cae9f 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/Cultivator.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/Cultivator.java @@ -10,7 +10,10 @@ import io.anuke.arc.math.RandomXS128; import io.anuke.arc.util.Time; import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.entities.type.TileEntity; +import io.anuke.mindustry.graphics.Pal; +import io.anuke.mindustry.ui.Bar; import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.meta.Attribute; import java.io.DataInput; import java.io.DataOutput; @@ -46,6 +49,21 @@ public class Cultivator extends GenericCrafter{ entity.warmup = Mathf.lerpDelta(entity.warmup, entity.cons.valid() ? 1f : 0f, 0.015f); } + @Override + public void setBars(){ + super.setBars(); + bars.add("multiplier", entity -> new Bar(() -> + Core.bundle.format("blocks.efficiency", + ((((CultivatorEntity)entity).boost + 1f) * ((CultivatorEntity)entity).warmup)*100f,1), + () -> Pal.ammo, + () -> ((CultivatorEntity)entity).warmup)); + } + + @Override + public void drawPlace(int x, int y, int rotation, boolean valid){ + drawPlaceText(Core.bundle.format("blocks.efficiency", (1+sumAttribute(Attribute.spores, x, y))*100, 1), x, y, valid); + } + @Override public void draw(Tile tile){ CultivatorEntity entity = tile.entity(); @@ -84,8 +102,23 @@ public class Cultivator extends GenericCrafter{ return new CultivatorEntity(); } + @Override + public void onProximityAdded(Tile tile){ + super.onProximityAdded(tile); + + CultivatorEntity entity = tile.entity(); + entity.boost = sumAttribute(Attribute.spores, tile.x, tile.y); + } + + @Override + protected float getProgressIncrease(TileEntity entity, float baseTime){ + CultivatorEntity c = (CultivatorEntity)entity; + return super.getProgressIncrease(entity, baseTime) * (1f + c.boost); + } + public static class CultivatorEntity extends GenericCrafterEntity{ public float warmup; + public float boost; @Override public void write(DataOutput stream) throws IOException{ diff --git a/core/src/io/anuke/mindustry/world/blocks/production/Drill.java b/core/src/io/anuke/mindustry/world/blocks/production/Drill.java index 0d7d8c8e5a..7b4713aeb7 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/Drill.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/Drill.java @@ -18,6 +18,7 @@ import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.graphics.Layer; import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.type.ItemType; import io.anuke.mindustry.ui.Bar; import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; @@ -167,9 +168,6 @@ public class Drill extends Block{ public void update(Tile tile){ DrillEntity entity = tile.entity(); - if(Float.isNaN(entity.drillTime)) entity.drillTime = 0f; - if(Float.isNaN(entity.warmup)) entity.warmup = 0f; - if(entity.dominantItem == null){ oreCount.clear(); itemArray.clear(); @@ -185,7 +183,7 @@ public class Drill extends Block{ } itemArray.sort((item1, item2) -> Integer.compare(oreCount.get(item1, 0), oreCount.get(item2, 0))); - itemArray.sort((item1, item2) -> item1.genOre && !item2.genOre ? 1 : item1.genOre == item2.genOre ? 0 : -1); + itemArray.sort((item1, item2) -> Boolean.compare(item1.type == ItemType.material, item2.type == ItemType.material)); if(itemArray.size == 0){ return; @@ -262,12 +260,12 @@ public class Drill extends Block{ } public Item getDrop(Tile tile){ - return tile.floor().itemDrop; + return tile.drop(); } public boolean isValid(Tile tile){ if(tile == null) return false; - Item drops = tile.floor().itemDrop; + Item drops = tile.drop(); return drops != null && drops.hardness <= tier; } diff --git a/core/src/io/anuke/mindustry/world/blocks/production/SolidPump.java b/core/src/io/anuke/mindustry/world/blocks/production/SolidPump.java index 226933c355..f91501c1cf 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/SolidPump.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/SolidPump.java @@ -1,17 +1,20 @@ package io.anuke.mindustry.world.blocks.production; import io.anuke.arc.Core; +import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.TextureRegion; -import io.anuke.mindustry.content.Liquids; +import io.anuke.arc.math.Mathf; import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.type.TileEntity; -import io.anuke.mindustry.type.Liquid; -import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.meta.BlockStat; +import io.anuke.mindustry.content.Liquids; import io.anuke.mindustry.entities.Effects; import io.anuke.mindustry.entities.Effects.Effect; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.math.Mathf; +import io.anuke.mindustry.entities.type.TileEntity; +import io.anuke.mindustry.graphics.Pal; +import io.anuke.mindustry.type.Liquid; +import io.anuke.mindustry.ui.Bar; +import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.meta.Attribute; +import io.anuke.mindustry.world.meta.BlockStat; /** * Pump that makes liquid from solids and takes in power. Only works on solid floor blocks. @@ -21,6 +24,8 @@ public class SolidPump extends Pump{ protected Effect updateEffect = Fx.none; protected float updateEffectChance = 0.02f; protected float rotateSpeed = 1f; + /**Attribute that is checked when calculating output.*/ + protected Attribute attribute; public SolidPump(String name){ super(name); @@ -34,11 +39,27 @@ public class SolidPump extends Pump{ liquidRegion = Core.atlas.find(name + "-liquid"); } + @Override + public void drawPlace(int x, int y, int rotation, boolean valid){ + if(attribute != null){ + drawPlaceText(Core.bundle.format("blocks.efficiency", (sumAttribute(attribute, x, y) + 1f)*100, 1), x, y, valid); + } + } + + @Override + public void setBars(){ + super.setBars(); + bars.add("efficiency", entity -> new Bar(() -> + Core.bundle.format("blocks.efficiency", + ((((SolidPumpEntity)entity).boost + 1f) * ((SolidPumpEntity)entity).warmup) * 100, 1), + () -> Pal.ammo, + () -> ((SolidPumpEntity)entity).warmup)); + } + @Override public void setStats(){ super.setStats(); - // stats.remove(BlockStat.liquidOutput); stats.add(BlockStat.liquidOutput, result); } @@ -76,6 +97,8 @@ public class SolidPump extends Pump{ if(isValid(tile)) fraction = 1f; } + fraction += entity.boost; + if(tile.entity.cons.valid() && typeLiquid(tile) < liquidCapacity - 0.001f){ float maxPump = Math.min(liquidCapacity - typeLiquid(tile), pumpAmount * entity.delta() * fraction * entity.power.satisfaction); tile.entity.liquids.add(result, maxPump); @@ -115,6 +138,16 @@ public class SolidPump extends Pump{ return new SolidPumpEntity(); } + @Override + public void onProximityAdded(Tile tile){ + super.onProximityAdded(tile); + + if(attribute != null){ + SolidPumpEntity entity = tile.entity(); + entity.boost = sumAttribute(attribute, tile.x, tile.y); + } + } + public float typeLiquid(Tile tile){ return tile.entity.liquids.total(); } @@ -122,5 +155,6 @@ public class SolidPump extends Pump{ public static class SolidPumpEntity extends TileEntity{ public float warmup; public float pumpTime; + public float boost; } } diff --git a/core/src/io/anuke/mindustry/world/blocks/sandbox/ItemSource.java b/core/src/io/anuke/mindustry/world/blocks/sandbox/ItemSource.java index 51a39117ec..c9b4e55d12 100644 --- a/core/src/io/anuke/mindustry/world/blocks/sandbox/ItemSource.java +++ b/core/src/io/anuke/mindustry/world/blocks/sandbox/ItemSource.java @@ -13,6 +13,12 @@ public class ItemSource extends Sorter{ solid = true; } + @Override + public void setBars(){ + super.setBars(); + bars.remove("items"); + } + @Override public boolean outputsItems(){ return true; diff --git a/core/src/io/anuke/mindustry/world/blocks/sandbox/LiquidSource.java b/core/src/io/anuke/mindustry/world/blocks/sandbox/LiquidSource.java index 641a768148..86d189c639 100644 --- a/core/src/io/anuke/mindustry/world/blocks/sandbox/LiquidSource.java +++ b/core/src/io/anuke/mindustry/world/blocks/sandbox/LiquidSource.java @@ -21,6 +21,7 @@ import java.io.DataOutput; import java.io.IOException; import static io.anuke.mindustry.Vars.content; +import static io.anuke.mindustry.Vars.control; public class LiquidSource extends Block{ @@ -71,8 +72,10 @@ public class LiquidSource extends Block{ for(int i = 0; i < items.size; i++){ final int f = i; - ImageButton button = cont.addImageButton("clear", "clear-toggle", 24, - () -> Call.setLiquidSourceLiquid(null, tile, items.get(f))).size(38).group(group).get(); + ImageButton button = cont.addImageButton("clear", "clear-toggle", 24, () -> { + Call.setLiquidSourceLiquid(null, tile, items.get(f)); + control.input(0).frag.config.hideConfig(); + }).size(38).group(group).get(); button.getStyle().imageUp = new TextureRegionDrawable(items.get(i).iconRegion); button.setChecked(entity.source.id == f); diff --git a/core/src/io/anuke/mindustry/world/blocks/storage/LaunchPad.java b/core/src/io/anuke/mindustry/world/blocks/storage/LaunchPad.java index 94875bac5b..206c63f1ac 100644 --- a/core/src/io/anuke/mindustry/world/blocks/storage/LaunchPad.java +++ b/core/src/io/anuke/mindustry/world/blocks/storage/LaunchPad.java @@ -34,7 +34,7 @@ public class LaunchPad extends StorageBlock{ if(entity.cons.valid() && world.isZone()){ for(Item item : Vars.content.items()){ - if(entity.items.get(item) >= itemCapacity && entity.timer.get(timerLaunch, launchTime)){ + if(entity.items.get(item) >= itemCapacity && entity.timer.get(timerLaunch, launchTime / entity.timeScale)){ //TODO play animation of some sort Effects.effect(Fx.dooropenlarge, tile); data.addItem(item, entity.items.get(item)); diff --git a/core/src/io/anuke/mindustry/world/blocks/storage/Unloader.java b/core/src/io/anuke/mindustry/world/blocks/storage/Unloader.java index ef37e6679f..b60fed4eba 100644 --- a/core/src/io/anuke/mindustry/world/blocks/storage/Unloader.java +++ b/core/src/io/anuke/mindustry/world/blocks/storage/Unloader.java @@ -41,6 +41,12 @@ public class Unloader extends Block implements SelectionTrait{ return !(block instanceof StorageBlock); } + @Override + public void setBars(){ + super.setBars(); + bars.remove("items"); + } + @Override public void playerPlaced(Tile tile){ Core.app.post(() -> Call.setSortedUnloaderItem(null, tile, lastItem)); @@ -57,7 +63,7 @@ public class Unloader extends Block implements SelectionTrait{ public void update(Tile tile){ SortedUnloaderEntity entity = tile.entity(); - if(tile.entity.timer.get(timerUnload, speed) && tile.entity.items.total() == 0){ + if(tile.entity.timer.get(timerUnload, speed / entity.timeScale) && tile.entity.items.total() == 0){ for(Tile other : tile.entity.proximity()){ if(other.interactable(tile.getTeam()) && other.block() instanceof StorageBlock && entity.items.total() == 0 && ((entity.sortItem == null && other.entity.items.total() > 0) || ((StorageBlock) other.block()).hasItem(other, entity.sortItem))){ @@ -77,7 +83,7 @@ public class Unloader extends Block implements SelectionTrait{ SortedUnloaderEntity entity = tile.entity(); - Draw.color(entity.sortItem == null ? Color.WHITE : entity.sortItem.color); + Draw.color(entity.sortItem == null ? Color.CLEAR : entity.sortItem.color); Draw.rect("blank", tile.worldx(), tile.worldy(), 2f, 2f); Draw.color(); } diff --git a/core/src/io/anuke/mindustry/world/blocks/units/UnitFactory.java b/core/src/io/anuke/mindustry/world/blocks/units/UnitFactory.java index d831e44595..2d75666b01 100644 --- a/core/src/io/anuke/mindustry/world/blocks/units/UnitFactory.java +++ b/core/src/io/anuke/mindustry/world/blocks/units/UnitFactory.java @@ -35,6 +35,7 @@ import java.io.DataOutput; import java.io.IOException; public class UnitFactory extends Block{ + //for attack mode protected float gracePeriodMultiplier = 15f; protected float speedupTime = 60f * 60f * 20; protected float maxSpeedup = 2f; @@ -57,14 +58,14 @@ public class UnitFactory extends Block{ } @Remote(called = Loc.server) - public static void onUnitFactorySpawn(Tile tile){ + public static void onUnitFactorySpawn(Tile tile, int spawns){ if(!(tile.entity instanceof UnitFactoryEntity) || !(tile.block() instanceof UnitFactory)) return; UnitFactoryEntity entity = tile.entity(); UnitFactory factory = (UnitFactory) tile.block(); entity.buildTime = 0f; - entity.spawned ++; + entity.spawned = spawns; Effects.shake(2f, 3f, entity); Effects.effect(Fx.producesmoke, tile.drawx(), tile.drawy()); @@ -182,7 +183,7 @@ public class UnitFactory extends Block{ if(entity.buildTime >= produceTime){ entity.buildTime = 0f; - Call.onUnitFactorySpawn(tile); + Call.onUnitFactorySpawn(tile, entity.spawned + 1); useContent(tile, type); for(ItemStack stack : consumes.items()){ diff --git a/core/src/io/anuke/mindustry/world/consumers/ConsumeItem.java b/core/src/io/anuke/mindustry/world/consumers/ConsumeItem.java index 2afce34150..d6806db4c5 100644 --- a/core/src/io/anuke/mindustry/world/consumers/ConsumeItem.java +++ b/core/src/io/anuke/mindustry/world/consumers/ConsumeItem.java @@ -4,6 +4,7 @@ import io.anuke.arc.scene.ui.layout.Table; import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Item.Icon; +import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.ui.ItemImage; import io.anuke.mindustry.ui.ReqImage; import io.anuke.mindustry.world.Block; @@ -60,6 +61,6 @@ public class ConsumeItem extends Consume{ @Override public void display(BlockStats stats){ - stats.add(boost ? BlockStat.boostItem : BlockStat.inputItem, item); + stats.add(boost ? BlockStat.boostItem : BlockStat.inputItem, new ItemStack(item, amount)); } } diff --git a/core/src/io/anuke/mindustry/world/meta/Attribute.java b/core/src/io/anuke/mindustry/world/meta/Attribute.java new file mode 100644 index 0000000000..5f761f5359 --- /dev/null +++ b/core/src/io/anuke/mindustry/world/meta/Attribute.java @@ -0,0 +1,12 @@ +package io.anuke.mindustry.world.meta; + +public enum Attribute{ + /** Heat of this block. Used for calculating output of thermal generators.*/ + heat, + /** Spore content of this block. Used for increasing cultivator yield.*/ + spores, + /** Water content of this block. Used for increasing water extractor yield.*/ + water, + /** Oil content of this block. Used for increasing oil extractor yield.*/ + oil +} diff --git a/core/src/io/anuke/mindustry/world/meta/BlockStats.java b/core/src/io/anuke/mindustry/world/meta/BlockStats.java index 9dcd09db5e..d094b16672 100644 --- a/core/src/io/anuke/mindustry/world/meta/BlockStats.java +++ b/core/src/io/anuke/mindustry/world/meta/BlockStats.java @@ -1,20 +1,14 @@ package io.anuke.mindustry.world.meta; -import io.anuke.arc.Core; import io.anuke.arc.collection.ObjectMap.Entry; import io.anuke.arc.collection.OrderedMap; -import io.anuke.arc.util.Log; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.world.meta.values.*; -import java.util.Locale; - /**Hold and organizes a list of block stats.*/ public class BlockStats{ - private static final boolean errorWhenMissing = false; - private final OrderedMap> map = new OrderedMap<>(); private boolean dirty; @@ -50,22 +44,6 @@ public class BlockStats{ /**Adds a stat value.*/ public void add(BlockStat stat, StatValue value){ - if(!Core.bundle.has("blocks." + stat.name().toLowerCase(Locale.ROOT))){ - if(!errorWhenMissing){ - Log.err("Warning: No bundle entry for stat type \"" + stat + "\"!"); - }else{ - throw new RuntimeException("No bundle entry for stat type \"" + stat + "\"!"); - } - } - - if(!Core.bundle.has("category." + stat.category.name().toLowerCase(Locale.ROOT))){ - if(!errorWhenMissing){ - Log.err("Warning: No bundle entry for stat category \"" + stat.category + "\"!"); - }else{ - throw new RuntimeException("No bundle entry for stat category \"" + stat.category + "\"!"); - } - } - if(map.containsKey(stat.category) && map.get(stat.category).containsKey(stat)){ throw new RuntimeException("Duplicate stat entry: \"" + stat + "\" in block."); } diff --git a/core/src/io/anuke/mindustry/world/meta/values/NumberValue.java b/core/src/io/anuke/mindustry/world/meta/values/NumberValue.java index 8c8a058297..620bfc1186 100644 --- a/core/src/io/anuke/mindustry/world/meta/values/NumberValue.java +++ b/core/src/io/anuke/mindustry/world/meta/values/NumberValue.java @@ -16,10 +16,6 @@ public class NumberValue implements StatValue{ public NumberValue(float value, StatUnit unit){ this.unit = unit; this.value = value; - - if(unit != StatUnit.none && unit.localized().contains("???")){ - throw new RuntimeException("No bundle definition found for unit: '" + unit + "'"); - } } @Override diff --git a/core/src/io/anuke/mindustry/world/meta/values/StringValue.java b/core/src/io/anuke/mindustry/world/meta/values/StringValue.java index f51884621a..830d897ab6 100644 --- a/core/src/io/anuke/mindustry/world/meta/values/StringValue.java +++ b/core/src/io/anuke/mindustry/world/meta/values/StringValue.java @@ -8,7 +8,7 @@ public class StringValue implements StatValue{ private final String value; public StringValue(String value, Object... args){ - this.value = Strings.formatArgs(value, args); + this.value = Strings.format(value, args); } @Override diff --git a/core/src/io/anuke/mindustry/world/modules/ConsumeModule.java b/core/src/io/anuke/mindustry/world/modules/ConsumeModule.java index 9643377a7b..f2daa58255 100644 --- a/core/src/io/anuke/mindustry/world/modules/ConsumeModule.java +++ b/core/src/io/anuke/mindustry/world/modules/ConsumeModule.java @@ -18,9 +18,10 @@ public class ConsumeModule extends BlockModule{ public void update(){ boolean prevValid = valid(); valid = true; + boolean docons = entity.tile.block().shouldConsume(entity.tile); for(Consume cons : entity.tile.block().consumes.all()){ - if(cons.isUpdate() && prevValid && entity.tile.block().shouldConsume(entity.tile) && cons.valid(entity.getTile().block(), entity)){ + if(docons && cons.isUpdate() && prevValid && cons.valid(entity.getTile().block(), entity)){ cons.update(entity.getTile().block(), entity); } diff --git a/core/src/io/anuke/mindustry/world/modules/PowerModule.java b/core/src/io/anuke/mindustry/world/modules/PowerModule.java index fead3d97c7..265724c974 100644 --- a/core/src/io/anuke/mindustry/world/modules/PowerModule.java +++ b/core/src/io/anuke/mindustry/world/modules/PowerModule.java @@ -34,5 +34,6 @@ public class PowerModule extends BlockModule{ links.add(stream.readInt()); } satisfaction = stream.readFloat(); + if(Float.isNaN(satisfaction) || Float.isInfinite(satisfaction)) satisfaction = 0f; } } diff --git a/desktop/build.gradle b/desktop/build.gradle index 24358df109..48aa4e3236 100644 --- a/desktop/build.gradle +++ b/desktop/build.gradle @@ -6,25 +6,24 @@ sourceSets.main.java.srcDirs = ["src/"] project.ext.mainClassName = "io.anuke.mindustry.desktop.DesktopLauncher" project.ext.assetsDir = new File("../core/assets") -def PACKR_DIR = "$System.env.PACKR_DIR" +import com.badlogicgames.packr.PackrConfig +import com.badlogicgames.packr.Packr + +def JDK_DIR = "$System.env.PACKR_DIR" def ICON_DIR = new File("core/assets/sprites/icon.icns") ext.getPlatform = { - if(project.hasProperty("platform")){ - def lc = platform.toLowerCase() - if(lc == "windows64"){ - return "windows64" - }else if(lc == "windows32"){ - return "windows32" - }else if(lc == "linux"){ - return "linux64" - }else if(lc == "mac"){ - return "mac" - }else{ - throw new InvalidUserDataException("Invalid platform. Set platform with -Pplatform=windows/linux/mac") - } + def lc = project.hasProperty("platform") ? platform.toLowerCase() : "" + if(lc == "windows64"){ + return PackrConfig.Platform.Windows64 + }else if(lc == "windows32"){ + return PackrConfig.Platform.Windows32 + }else if(lc == "linux"){ + return PackrConfig.Platform.Linux64 + }else if(lc == "mac"){ + return PackrConfig.Platform.MacOS }else{ - throw new InvalidUserDataException("No platform defined. Set platform with -Pplatform=windows/linux/mac") + throw new InvalidUserDataException("Invalid platform. Set platform with -Pplatform=windows64/windows32/linux/mac") } } @@ -70,69 +69,68 @@ task dist(type: Jar){ } } -task clearOut(type: Delete){ - doLast{ - delete "packr-out/" - } -} - //note: call desktop:dist beforehand task packrCmd(){ doLast{ + def config = new PackrConfig() + config.with{ + config.executable = appName + verbose = true + platform = getPlatform() + bundleIdentifier = getPackage() + ".mac" + iconResource = ICON_DIR + outDir = file("packr-out/") + mainClass = project.ext.mainClassName + classpath = ["desktop/build/libs/desktop-release.jar"] + vmArgs = ["Djava.net.preferIPv4Stack=true"] + minimizeJre = "desktop/packr_minimize.json" + jdk = JDK_DIR + "jdk-${getPlatform().toString().toLowerCase()}.zip" - copy{ - into PACKR_DIR - from "build/libs/desktop-release.jar" + if(getPlatform() == PackrConfig.Platform.MacOS){ + vmArgs += "XstartOnFirstThread" + } } - exec{ - - commandLine("java", "-jar", PACKR_DIR + "packr.jar", - "--verbose", - "--bundle", getPackage() + ".mac", - "--platform", getPlatform(), - "--executable", appName, - "--output", "packr-out/", - "--mainclass", project.ext.mainClassName, - "--jdk", PACKR_DIR + "jdk-" + getPlatform() + ".zip", - "--icon", ICON_DIR.getAbsolutePath(), - "--vmargs", (getPlatform() == "mac" ? "XstartOnFirstThread" : "Xms256m"), - "Djava.net.preferIPv4Stack=true", - "--classpath", "--", PACKR_DIR + "config.json") - } - } -} - -task fixMac(type: Copy){ - dependsOn "packrCmd" - - into "packr-out/" + appName + ".app/Contents/" - from "packr-out/Contents/" - - doLast{ - delete{ - delete "packr-out/Contents/" - } - } -} - -task fixWindows32(type: Copy){ - dependsOn "packrCmd" - - into "packr-out/jre/bin/" - from PACKR_DIR + "zip.dll" - rename("zip.dll", "ojdkbuild_zlib.dll") - - doLast{ - copy{ - into "packr-out/jre/bin/" - from PACKR_DIR + "zip.dll" - } + new Packr().pack(config) } } task packrZip(){ + task clearOut(type: Delete){ + doLast{ + delete "packr-out/" + } + } + + task fixMac(type: Copy){ + dependsOn "packrCmd" + + into "packr-out/" + appName + ".app/Contents/" + from "packr-out/Contents/" + + doLast{ + delete{ + delete "packr-out/Contents/" + } + } + } + + task fixWindows32(type: Copy){ + dependsOn "packrCmd" + + into "packr-out/jre/bin/" + from JDK_DIR + "zip.dll" + rename("zip.dll", "ojdkbuild_zlib.dll") + + doLast{ + copy{ + into "packr-out/jre/bin/" + from JDK_DIR + "zip.dll" + } + } + } + dependsOn "packrCmd" finalizedBy "clearOut" @@ -146,12 +144,12 @@ task packrZip(){ dependsOn "fixWindows32" } - task zip(type: Zip){ + task rzip(type: Zip){ from "packr-out/" archiveName "$appName-${getPlatform()}-${getVersionString()}.zip" destinationDir(file("packr-export")) } - finalizedBy 'zip' + finalizedBy 'rzip' } } diff --git a/desktop/packr_minimize.json b/desktop/packr_minimize.json new file mode 100644 index 0000000000..0887fdf720 --- /dev/null +++ b/desktop/packr_minimize.json @@ -0,0 +1,82 @@ +{ + "reduce": [ + { + "archive": "jre/lib/rt.jar", + "paths": [ + + "javax/transaction", + "javax/tools", + "javax/swing", + "javax/sql", + "javax/smartcardio", + "javax/rmi", + "javax/print", + "javax/naming", + "javax/management", + "javax/lang", + "javax/jws", + "javax/swing", + "javax/imageio", + "javax/annotation", + "javax/activity", + "javax/activation", + "javax/accessibility", + "com/sun/corba", + "com/sun/jmx", + "com/sun/jndi", + "com/sun/xml", + "com/sun/script", + "com/sun/media", + "com/sun/naming", + "java/awt", + + "com/sun/org/apache/xpath", + + "com/sun/rowset", + "com/sun/script", + "sun/applet", + "sun/corba", + "sun/management" + ] + }, + { + "archive": "jre/lib/charsets.jar", + "paths": [ + ] + }, + { + "archive": "jre/lib/jsse.jar", + "paths": [ + ] + }, + { + "archive": "jre/lib/resources.jar", + "paths": [ + ] + } + ], + "remove": [ + { + "platform": "*", + "paths": [ + "jre/lib/rhino.jar" + ] + }, + { + "platform": "linux", + "paths": [ + "jre/lib/amd64/libawt.so", + "jre/lib/amd64/libawt_xawt.so", + "jre/lib/amd64/libjawt.so" + ] + }, + { + "platform": "windows", + "paths": [ + "jre/bin/*.exe", + "jre/bin/client", + "jre/bin/awt.dll" + ] + } + ] +} diff --git a/desktop/src/io/anuke/mindustry/desktop/CrashHandler.java b/desktop/src/io/anuke/mindustry/desktop/CrashHandler.java index c2e23ee01b..1de445dfc3 100644 --- a/desktop/src/io/anuke/mindustry/desktop/CrashHandler.java +++ b/desktop/src/io/anuke/mindustry/desktop/CrashHandler.java @@ -9,6 +9,7 @@ import io.anuke.arc.util.serialization.JsonWriter.OutputType; import io.anuke.mindustry.Vars; import io.anuke.mindustry.game.Version; import io.anuke.mindustry.net.Net; +import org.lwjgl.util.tinyfd.TinyFileDialogs; import java.io.PrintWriter; import java.io.StringWriter; @@ -25,34 +26,24 @@ public class CrashHandler{ try{ //check crash report setting - if(!Core.settings.getBool("crashreport")){ + if(!Core.settings.getBool("crashreport", true)){ return; } }catch(Throwable ignored){ - //don't send since we don't know if the user has the setting set - return; - } - - if(!OS.isMac){ - try{ - javax.swing.UIManager.setLookAndFeel(javax.swing.UIManager.getSystemLookAndFeelClassName()); - }catch(Throwable ignored){} + //if there's no settings init we don't know what the user wants but chances are it's an important crash, so send it anyway } boolean badGPU = false; - if(!OS.isMac && e.getMessage() != null && (e.getMessage().contains("Couldn't create window") || e.getMessage().contains("OpenGL 2.0 or higher"))){ - try{ - javax.swing.JOptionPane.showMessageDialog(null, "Your graphics card does not support OpenGL 2.0!\n" + - "Try to update your graphics drivers.\n\n" + - "(If that doesn't work, your computer just doesn't support Mindustry.)", - "oh no", javax.swing.JOptionPane.INFORMATION_MESSAGE); - badGPU = true; - }catch(Throwable ignored){} + if(e.getMessage() != null && (e.getMessage().contains("Couldn't create window") || e.getMessage().contains("OpenGL 2.0 or higher"))){ + + dialog(() -> TinyFileDialogs.tinyfd_messageBox("oh no", "Your graphics card does not support OpenGL 2.0!\n" + + "Try to update your graphics drivers.\n\n" + + "(If that doesn't work, your computer just doesn't support Mindustry.)", "ok", "error", true)); + badGPU = true; } - //don't create crash logs for me (anuke), as it's expected - //also don't create logs for custom builds + //don't create crash logs for me (anuke) or custom builds, as it's expected if(System.getProperty("user.name").equals("anuke") || Version.build == -1) return; boolean netActive = false, netServer = false; @@ -83,14 +74,12 @@ public class CrashHandler{ try{ Path path = Paths.get(OS.getAppDataDirectoryString(Vars.appName), "crashes", - "crash-report-" + DateTimeFormatter.ofPattern("MM dd yyyy HH mm ss").format(LocalDateTime.now()) + ".txt"); + "crash-report-" + DateTimeFormatter.ofPattern("MM_dd_yyyy_HH_mm_ss").format(LocalDateTime.now()) + ".txt"); Files.createDirectories(Paths.get(OS.getAppDataDirectoryString(Vars.appName), "crashes")); - Files.write(path, parseException(e).getBytes()); if(!badGPU){ - javax.swing.JOptionPane.showMessageDialog(null, "A crash has occured. It has been saved in:\n" + path.toAbsolutePath().toString(), - "oh no", javax.swing.JOptionPane.INFORMATION_MESSAGE); + dialog(() -> TinyFileDialogs.tinyfd_messageBox("oh no", "A crash has occured. It has been saved in:\n" + path.toAbsolutePath().toString(), "ok", "error", true)); } }catch(Throwable t){ Log.err("Failed to save local crash report."); @@ -107,8 +96,12 @@ public class CrashHandler{ System.exit(1); }); - //sleep forever - try{ Thread.sleep(Long.MAX_VALUE); }catch(InterruptedException ignored){} + //sleep for 10 seconds or until crash report is sent + try{ Thread.sleep(10000); }catch(InterruptedException ignored){} + } + + private static void dialog(Runnable r){ + new Thread(r).start(); } private static String parseException(Throwable e){ diff --git a/desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java b/desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java index 28179d163b..8be38a1feb 100644 --- a/desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java +++ b/desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java @@ -20,6 +20,7 @@ public class DesktopLauncher extends Lwjgl3Application{ Lwjgl3ApplicationConfiguration config = new Lwjgl3ApplicationConfiguration(); config.setTitle("Mindustry"); config.setMaximized(true); + config.setBackBufferConfig(8, 8, 8, 8, 0, 0, 0); config.setWindowedMode(960, 540); config.setWindowIcon("sprites/icon.png"); diff --git a/desktop/src/io/anuke/mindustry/desktop/DesktopPlatform.java b/desktop/src/io/anuke/mindustry/desktop/DesktopPlatform.java index 24c8be9015..b1b855d048 100644 --- a/desktop/src/io/anuke/mindustry/desktop/DesktopPlatform.java +++ b/desktop/src/io/anuke/mindustry/desktop/DesktopPlatform.java @@ -54,9 +54,9 @@ public class DesktopPlatform extends Platform{ if(world.getMap() == null){ presence.details = "Unknown Map"; }else if(!state.rules.waves){ - presence.details = Strings.capitalize(world.getMap().name); + presence.details = Strings.capitalize(world.getMap().name()); }else{ - presence.details = Strings.capitalize(world.getMap().name) + " | Wave " + state.wave; + presence.details = Strings.capitalize(world.getMap().name()) + " | Wave " + state.wave; presence.largeImageText = "Wave " + state.wave; } diff --git a/ios/src/io/anuke/mindustry/IOSLauncher.java b/ios/src/io/anuke/mindustry/IOSLauncher.java index cc7d8dd154..a4ce1935dd 100644 --- a/ios/src/io/anuke/mindustry/IOSLauncher.java +++ b/ios/src/io/anuke/mindustry/IOSLauncher.java @@ -113,7 +113,7 @@ public class IOSLauncher extends IOSApplication.Delegate { ui.editor.show(); } - ui.editor.beginEditMap(file.read()); + ui.editor.beginEditMap(file); }); } }); diff --git a/server/build.gradle b/server/build.gradle index 6f22ffa04c..51240b5170 100644 --- a/server/build.gradle +++ b/server/build.gradle @@ -31,6 +31,10 @@ task dist(type: Jar) { from files(sourceSets.main.output.resourcesDir) from {configurations.compile.collect {zipTree(it)}} from files(project.assetsDir) + exclude("sprites/**") + exclude("fonts/**") + exclude("com/badlogic/gdx/**") + exclude("bundles/**") writeVersion() diff --git a/server/src/io/anuke/mindustry/server/ServerControl.java b/server/src/io/anuke/mindustry/server/ServerControl.java index 180430a1ee..4fd507e487 100644 --- a/server/src/io/anuke/mindustry/server/ServerControl.java +++ b/server/src/io/anuke/mindustry/server/ServerControl.java @@ -46,7 +46,6 @@ public class ServerControl implements ApplicationListener{ private FileHandle currentLogFile; private boolean inExtraRound; private Task lastTask; - private RulePreset lastPreset; public ServerControl(String[] args){ Core.settings.defaults( @@ -144,11 +143,11 @@ public class ServerControl implements ApplicationListener{ Call.onInfoMessage((state.rules.pvp ? "[YELLOW]The " + event.winner.name() + " team is victorious![]" : "[SCARLET]Game over![]") - + "\nNext selected map:[accent] "+map.name+"[]" - + (map.meta.author() != null ? " by[accent] " + map.meta.author() + "[]" : "") + "."+ + + "\nNext selected map:[accent] "+map.name()+"[]" + + (map.author() != null ? " by[accent] " + map.author() + "[]" : "") + "."+ "\nNew game begins in " + roundExtraTime + " seconds."); - info("Selected next map to be {0}.", map.name); + info("Selected next map to be {0}.", map.name()); Map fmap = map; @@ -199,7 +198,7 @@ public class ServerControl implements ApplicationListener{ if(lastTask != null) lastTask.cancel(); - Map result = world.maps.all().find(map -> map.name.equalsIgnoreCase(arg[0])); + Map result = world.maps.all().find(map -> map.name().equalsIgnoreCase(arg[0])); if(result == null){ err("No map with name &y'{0}'&lr found.", arg[0]); @@ -229,7 +228,7 @@ public class ServerControl implements ApplicationListener{ host(); }catch(MapException e){ - Log.err(e.map.getDisplayName() + ": " + e.getMessage()); + Log.err(e.map.name() + ": " + e.getMessage()); } }); @@ -252,7 +251,7 @@ public class ServerControl implements ApplicationListener{ if(!world.maps.all().isEmpty()){ info("Maps:"); for(Map map : world.maps.all()){ - info(" &ly{0}: &lb&fi{1} / {2}x{3}", map.name, map.custom ? "Custom" : "Default", map.meta.width, map.meta.height); + info(" &ly{0}: &lb&fi{1} / {2}x{3}", map.name(), map.custom ? "Custom" : "Default", map.width, map.height); } }else{ info("No maps found."); @@ -265,7 +264,7 @@ public class ServerControl implements ApplicationListener{ info("Status: &rserver closed"); }else{ info("Status:"); - info(" &lyPlaying on map &fi{0}&fb &lb/&ly Wave {1}", Strings.capitalize(world.getMap().name), state.wave); + info(" &lyPlaying on map &fi{0}&fb &lb/&ly Wave {1}", Strings.capitalize(world.getMap().name()), state.wave); if(state.rules.waves){ info("&ly {0} enemies.", unitGroups[Team.red.ordinal()].size()); @@ -306,7 +305,7 @@ public class ServerControl implements ApplicationListener{ } }); - handler.register("fillitems", "[team]", "Fill the core with 2000 items.", arg -> { + handler.register("fillitems", "[team]", "Fill the core with items.", arg -> { if(!state.is(State.playing)){ err("Not playing. Host first."); return; @@ -322,7 +321,7 @@ public class ServerControl implements ApplicationListener{ for(Item item : content.items()){ if(item.type == ItemType.material){ - state.teams.get(team).cores.first().entity.items.add(item, 2000); + state.teams.get(team).cores.first().entity.items.set(item, state.teams.get(team).cores.first().block().itemCapacity); } } @@ -665,7 +664,7 @@ public class ServerControl implements ApplicationListener{ try{ r.run(); }catch(MapException e){ - Log.err(e.map.getDisplayName() + ": " + e.getMessage()); + Log.err(e.map.name() + ": " + e.getMessage()); Net.closeServer(); } } diff --git a/tests/src/test/java/ApplicationTests.java b/tests/src/test/java/ApplicationTests.java index f67122d9a7..91958bf7ab 100644 --- a/tests/src/test/java/ApplicationTests.java +++ b/tests/src/test/java/ApplicationTests.java @@ -194,8 +194,8 @@ public class ApplicationTests{ resetWorld(); SaveIO.loadFromSlot(0); - assertEquals(world.width(), map.meta.width); - assertEquals(world.height(), map.meta.height); + assertEquals(world.width(), map.width); + assertEquals(world.height(), map.height); assertTrue(state.teams.get(defaultTeam).cores.size > 0); } diff --git a/tests/src/test/java/MapTests.java b/tests/src/test/java/MapTests.java new file mode 100644 index 0000000000..689c7f5d22 --- /dev/null +++ b/tests/src/test/java/MapTests.java @@ -0,0 +1,11 @@ +import org.junit.jupiter.api.BeforeAll; + +public class MapTests{ + + @BeforeAll + static void launchApplication(){ + ApplicationTests.launchApplication(); + } + + //TODO +} diff --git a/tests/src/test/java/WorldTests.java b/tests/src/test/java/WorldTests.java new file mode 100644 index 0000000000..91c8fdce81 --- /dev/null +++ b/tests/src/test/java/WorldTests.java @@ -0,0 +1,117 @@ +import static io.anuke.mindustry.Vars.logic; +import static io.anuke.mindustry.Vars.state; +import static io.anuke.mindustry.Vars.world; +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import io.anuke.arc.util.Time; +import io.anuke.mindustry.content.Blocks; +import io.anuke.mindustry.core.GameState.State; +import io.anuke.mindustry.world.Tile; + +public class WorldTests { + static Tile[][] tiles; + + @BeforeAll + static void launchApplication(){ + ApplicationTests.launchApplication(); + world.createTiles(10,10); + tiles = world.getTiles(); + } + + @BeforeEach + void resetWorld(){ + Time.setDeltaProvider(() -> 1f); + logic.reset(); + state.set(State.menu); + } + + @Test + void addDarkness_allSolid_maxDarkness(){ + fillWith(Blocks.rocks.id); + world.addDarkness(tiles); + + for(int x = 0; x < tiles.length; x++) { + for (int y = 0; y < tiles[0].length; y++) { + assertEquals(4, tiles[x][y].getRotation()); + } + } + } + + @Test + void addDarkness_allSyntethic_noDarkness(){ + fillWith(Blocks.copperWall.id); + world.addDarkness(tiles); + + for(int x = 0; x < tiles.length; x++) { + for (int y = 0; y < tiles[0].length; y++) { + assertEquals(0, tiles[x][y].getRotation()); + } + } + } + + @Test + void addDarkness_allNotSolid_noDarkness(){ + fillWith(Blocks.air.id); + world.addDarkness(tiles); + + for(int x = 0; x < tiles.length; x++) { + for (int y = 0; y < tiles[0].length; y++) { + assertEquals(0, tiles[x][y].getRotation()); + } + } + } + + @Test + void addDarkness_allNotFilled_noDarkness(){ + fillWith(Blocks.cliffs.id); + world.addDarkness(tiles); + + for(int x = 0; x < tiles.length; x++) { + for (int y = 0; y < tiles[0].length; y++) { + assertEquals(0, tiles[x][y].getRotation()); + } + } + } + + @Test + void addDarkness_oneNotSolidMiddle_noDarkness(){ + fillWith(Blocks.rocks.id); + tiles[5][5] = new Tile(5, 5, (byte)0, Blocks.copperWall.id, (byte)0, (byte)0); + world.addDarkness(tiles); + + for(int x = 0; x < tiles.length; x++) { + for (int y = 0; y < tiles[0].length; y++) { + byte darkness = tiles[x][y].getRotation(); + int distance = Math.abs(x - 5) + Math.abs(y - 5); + assertEquals(Math.min(Math.max(distance - 1, 0), 4), darkness); + } + } + } + + @Test + void addDarkness_oneNotSolidCorner_noDarkness(){ + fillWith(Blocks.rocks.id); + tiles[7][7] = new Tile(5, 5, (byte)0, Blocks.copperWall.id, (byte)0, (byte)0); + world.addDarkness(tiles); + + for(int x = 0; x < tiles.length; x++) { + for (int y = 0; y < tiles[0].length; y++) { + byte darkness = tiles[x][y].getRotation(); + int distance = Math.abs(x - 7) + Math.abs(y - 7); + assertEquals(Math.min(Math.max(distance - 1, 0), 4), darkness); + } + } + } + + private static void fillWith(byte tileID){ + for(int x = 0; x < tiles.length; x++) { + for (int y = 0; y < tiles[0].length; y++) { + tiles[x][y] = new Tile(x, y, (byte)0, tileID, (byte)0, (byte)0); + } + } + } +} diff --git a/tests/src/test/java/power/DirectConsumerTests.java b/tests/src/test/java/power/DirectConsumerTests.java index 88233734ce..5298c27fde 100644 --- a/tests/src/test/java/power/DirectConsumerTests.java +++ b/tests/src/test/java/power/DirectConsumerTests.java @@ -16,13 +16,13 @@ public class DirectConsumerTests extends PowerTestFixture{ @Test void noPowerRequestedWithNoItems(){ - testUnitFactory(0, 0, 0.08f, 0.08f, 0f); + testUnitFactory(0, 0, 0.08f, 0.08f, 1f); } @Test void noPowerRequestedWithInsufficientItems(){ - testUnitFactory(30, 0, 0.08f, 0.08f, 0f); - testUnitFactory(0, 30, 0.08f, 0.08f, 0f); + testUnitFactory(30, 0, 0.08f, 0.08f, 1f); + testUnitFactory(0, 30, 0.08f, 0.08f, 1f); } @Test diff --git a/tests/src/test/java/power/PowerTests.java b/tests/src/test/java/power/PowerTests.java index 4af34d9c88..a722e4ed69 100644 --- a/tests/src/test/java/power/PowerTests.java +++ b/tests/src/test/java/power/PowerTests.java @@ -41,8 +41,8 @@ public class PowerTests extends PowerTestFixture{ // That's why we inject the description into the test method for now. // Additional Note: If you don't see any labels in front of the values supplied as function parameters, use a better IDE like IntelliJ IDEA. dynamicTest("01", () -> simulateDirectConsumption(0.0f, 1.0f, 0.0f, "0.0 produced, 1.0 consumed (no power available)")), - dynamicTest("02", () -> simulateDirectConsumption(0.0f, 0.0f, 0.0f, "0.0 produced, 0.0 consumed (no power anywhere)")), - dynamicTest("03", () -> simulateDirectConsumption(1.0f, 0.0f, 0.0f, "1.0 produced, 0.0 consumed (no power requested)")), + dynamicTest("02", () -> simulateDirectConsumption(0.0f, 0.0f, 1.0f, "0.0 produced, 0.0 consumed (no power anywhere)")), + dynamicTest("03", () -> simulateDirectConsumption(1.0f, 0.0f, 1.0f, "1.0 produced, 0.0 consumed (no power requested)")), dynamicTest("04", () -> simulateDirectConsumption(1.0f, 1.0f, 1.0f, "1.0 produced, 1.0 consumed (stable consumption)")), dynamicTest("05", () -> simulateDirectConsumption(0.5f, 1.0f, 0.5f, "0.5 produced, 1.0 consumed (power shortage)")), dynamicTest("06", () -> simulateDirectConsumption(1.0f, 0.5f, 1.0f, "1.0 produced, 0.5 consumed (power excess)")), diff --git a/tools/build.gradle b/tools/build.gradle index 3eace0a0c7..11c12fa338 100644 --- a/tools/build.gradle +++ b/tools/build.gradle @@ -11,6 +11,7 @@ import java.awt.image.BufferedImage def outFolder = "../core/assets-raw/sprites_out/" def genFolder = "../core/assets-raw/sprites_out/generated/" +def packFile = "../core/assets-raw/sprites/pack.json" def doAntialias = !project.hasProperty("disableAntialias") def antialias = {File file -> @@ -87,6 +88,7 @@ def antialias = {File file -> ImageIO.write(out, "png", file) } + task swapColors(){ doLast{ if (project.hasProperty("colors")) { diff --git a/tools/src/io/anuke/mindustry/Generators.java b/tools/src/io/anuke/mindustry/Generators.java index e2a030ea3f..5989906d99 100644 --- a/tools/src/io/anuke/mindustry/Generators.java +++ b/tools/src/io/anuke/mindustry/Generators.java @@ -1,6 +1,7 @@ package io.anuke.mindustry; import io.anuke.arc.graphics.Color; +import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Log; @@ -16,6 +17,7 @@ import io.anuke.mindustry.world.blocks.OreBlock; import java.io.IOException; import java.nio.file.Files; +import java.nio.file.Paths; import static io.anuke.mindustry.Vars.content; import static io.anuke.mindustry.Vars.tilesize; @@ -26,11 +28,24 @@ public class Generators { ImagePacker.generate("block-icons", () -> { Image colors = new Image(256, 1); - Color outlineColor = new Color(0, 0, 0, 0.2f); + Color outlineColor = new Color(0, 0, 0, 0.3f); for(Block block : content.blocks()){ TextureRegion[] regions = block.getGeneratedIcons(); + try{ + if(block instanceof Floor){ + block.load(); + for(TextureRegion region : block.variantRegions()){ + GenRegion gen = (GenRegion)region; + if(gen.path == null) continue; + Files.copy(gen.path, Paths.get("../editor/editor-" + gen.path.getFileName())); + } + } + }catch(IOException e){ + throw new RuntimeException(e); + } + if(regions.length == 0){ continue; } @@ -91,6 +106,8 @@ public class Generators { image.save(block.name + "-icon-full"); } + image.save("../editor/" + block.name + "-icon-editor"); + for(Icon icon : Icon.values()){ if(icon.size == 0 || (icon.size == image.width() && icon.size == image.height())) continue; Image scaled = new Image(icon.size, icon.size); @@ -149,8 +166,8 @@ public class Generators { int off = image.width()/2 - mech.weapon.region.getWidth()/2; - image.draw(mech.weapon.region, -(int)mech.weaponOffsetX + off, (int)mech.weaponOffsetY + off + 4, false, false); - image.draw(mech.weapon.region, (int)mech.weaponOffsetX + off, (int)mech.weaponOffsetY + off + 4, true, false); + image.draw(mech.weapon.region, -(int)mech.weaponOffsetX + off, (int)mech.weaponOffsetY + off, false, false); + image.draw(mech.weapon.region, (int)mech.weaponOffsetX + off, (int)mech.weaponOffsetY + off, true, false); image.save("mech-icon-" + mech.name); @@ -171,14 +188,12 @@ public class Generators { image.draw(type.legRegion, true, false); image.draw(type.region); - image.draw(type.weapon.region, - -(int)type.weapon.width + image.width()/2 - type.weapon.region.getWidth()/2, - (int)type.weaponOffsetY - image.height()/2 - type.weapon.region.getHeight()/2 + 1, - false, false); - image.draw(type.weapon.region, - (int)type.weapon.width + image.width()/2 - type.weapon.region.getWidth()/2, - (int)type.weaponOffsetY - image.height()/2 - type.weapon.region.getHeight()/2 + 1, - true, false); + for(boolean b : Mathf.booleans){ + image.draw(type.weapon.region, + (int)(Mathf.sign(b) * type.weapon.width / Draw.scl + image.width()/2 - type.weapon.region.getWidth()/2), + (int)(type.weaponOffsetY / Draw.scl + image.height()/2f - type.weapon.region.getHeight()/2f), + b, false); + } image.save("unit-icon-" + type.name); } @@ -190,11 +205,10 @@ public class Generators { OreBlock ore = (OreBlock)block; Item item = ore.itemDrop; - Block base = ore.base; for (int i = 0; i < 3; i++) { //get base image to draw on - Image image = ImagePacker.get(base.name + (i+1)); + Image image = new Image(32, 32); Image shadow = ImagePacker.get(item.name + (i+1)); int offset = image.width()/tilesize; @@ -212,7 +226,8 @@ public class Generators { } image.draw(ImagePacker.get(item.name + (i+1))); - image.save("ore-" + item.name + "-" + base.name + (i+1)); + image.save("../blocks/environment/ore-" + item.name + (i+1)); + image.save("../editor/editor-ore-" + item.name + (i+1)); //save icons image.save(block.name + "-icon-full"); @@ -247,7 +262,7 @@ public class Generators { } } - result.save(floor.name + "-edge"); + result.save("../blocks/environment/" + floor.name + "-edge"); }catch(Exception ignored){} } diff --git a/tools/src/io/anuke/mindustry/ImagePacker.java b/tools/src/io/anuke/mindustry/ImagePacker.java index ee1a00b811..6ec867511a 100644 --- a/tools/src/io/anuke/mindustry/ImagePacker.java +++ b/tools/src/io/anuke/mindustry/ImagePacker.java @@ -2,6 +2,7 @@ package io.anuke.mindustry; import io.anuke.arc.Core; import io.anuke.arc.collection.ObjectMap; +import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.TextureAtlas; import io.anuke.arc.graphics.g2d.TextureAtlas.AtlasRegion; import io.anuke.arc.graphics.g2d.TextureRegion; @@ -95,6 +96,8 @@ public class ImagePacker{ } }; + Draw.scl = 1f/Core.atlas.find("scale_marker").getWidth(); + Time.mark(); Generators.generate(); Log.info("&ly[Generator]&lc Total time to generate: &lg{0}&lcms", Time.elapsed()); @@ -131,7 +134,7 @@ public class ImagePacker{ } static void err(String message, Object... args){ - throw new IllegalArgumentException(Strings.formatArgs(message, args)); + throw new IllegalArgumentException(Strings.format(message, args)); } static class GenRegion extends AtlasRegion{