diff --git a/.gitignore b/.gitignore index 00ff121460..2377dbee42 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,8 @@ logs/ /server/build/ /test_files/ /annotations/build/ +/desktop-sdl/build/ +desktop-sdl/build/ /android/assets/mindustry-maps/ /android/assets/mindustry-saves/ /core/assets/gifexport/ diff --git a/.travis.yml b/.travis.yml index 4cf6a09aac..171280c268 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,20 +1,28 @@ jdk: - - openjdk8 +- 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}" +- 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}" deploy: - provider: releases - skip_cleanup: true - draft: false - api_key: - secure: Cv5wFtWt62/A24EvSEQvMow7gKPbZ3oATEFPuSghhB2TQz1dA40Zee3Qvk4LFlpLrhYo4K0ZSczCZRGpR+hCd8+Dpww52bheYEvWuh3ZQfvu/fXtEx2j5PwP1qMpmIgSxETV/gkD7l9FImdh0VzktYiAvQfmi0bEocG9/D4QwjFpNat7iwBdcMiw1MvAygpdIWRsjiw0RKlB2mWarmoHhQ7Gu7qlU3j50uaEvcrtmU0pBUPggNQwQRv32i9NPvNFxrqqlUjDLIS8JFea99zCkp8BwYqbEvBIMzd+Qip1/stLJJA3+cDUClbsDtg8rAVetzpOrdLEEBmqShFe5MDl2yEHcsgpN9CFsyTaUfvB3P3rVjizvycMm42IsUkXQiarm5xTQ/TIA8Rd8AHiSKuweNCg1Fd5SFaRtKy8JVLXuxyfUccmyje6hhz2L4lS2Wfj3mAG7sqZUCXhWP79EKdGkiPOjKv4CwXEKmuH3BMVqPlNUZJr9Eg3sV1FG0h2l+MVOOnR635qdUbb49sYojYxVruMLX0BH1c4ZCu230m8CUoWA1Em1QNI75ya7+9Y5T6AsgWDVpBvdUo9fWNbdp+VQ0GskFQsJD5wtnxbcbHeFiERAgGBm7z6qt9u9LrQpBH+dsW52ADvYsu3L4nQEa+sdMHwTTwmGY+iUvsxu0DqxGg= - file: - - "desktop/build/libs/desktop-release.jar" - - "server/build/libs/server-release.jar" - on: - repo: Anuken/Mindustry - tags: true + - provider: releases + skip_cleanup: true + draft: false + api_key: + secure: Cv5wFtWt62/A24EvSEQvMow7gKPbZ3oATEFPuSghhB2TQz1dA40Zee3Qvk4LFlpLrhYo4K0ZSczCZRGpR+hCd8+Dpww52bheYEvWuh3ZQfvu/fXtEx2j5PwP1qMpmIgSxETV/gkD7l9FImdh0VzktYiAvQfmi0bEocG9/D4QwjFpNat7iwBdcMiw1MvAygpdIWRsjiw0RKlB2mWarmoHhQ7Gu7qlU3j50uaEvcrtmU0pBUPggNQwQRv32i9NPvNFxrqqlUjDLIS8JFea99zCkp8BwYqbEvBIMzd+Qip1/stLJJA3+cDUClbsDtg8rAVetzpOrdLEEBmqShFe5MDl2yEHcsgpN9CFsyTaUfvB3P3rVjizvycMm42IsUkXQiarm5xTQ/TIA8Rd8AHiSKuweNCg1Fd5SFaRtKy8JVLXuxyfUccmyje6hhz2L4lS2Wfj3mAG7sqZUCXhWP79EKdGkiPOjKv4CwXEKmuH3BMVqPlNUZJr9Eg3sV1FG0h2l+MVOOnR635qdUbb49sYojYxVruMLX0BH1c4ZCu230m8CUoWA1Em1QNI75ya7+9Y5T6AsgWDVpBvdUo9fWNbdp+VQ0GskFQsJD5wtnxbcbHeFiERAgGBm7z6qt9u9LrQpBH+dsW52ADvYsu3L4nQEa+sdMHwTTwmGY+iUvsxu0DqxGg= + file: + - desktop/build/libs/desktop-release.jar + - server/build/libs/server-release.jar + on: + repo: Anuken/Mindustry + tags: true + - provider: script + script: bash update_wiki.sh + on: + repo: Anuken/Mindustry + tags: true +env: + global: + secure: TqlUl/ojjkCMVOGbCTKz7Cnr4F08UyWzY/CiJ0vvUOGJGZ1qm7XavAlDf5XT0egU4mvr37THubFO8vojbqmrmy0oZnYh3njKFA8axgyZ8PyKkjGHOfd0i6qyEWsOr9H90/2X8r3LwEeLaDFyHpu3wljIGBjweg53g2qwmDwCFa9UR80FJZ+xDB+rD6B3cXT0DTEkCoLZXLqXm0Y3HvBdSuBL1LR/FNb2BSxNq+tNLGiz1kdQZV5erausbbZypBoGxzz63xAnyz2kkFz73A8xQYVTzGbFodTPz7HM13GVZ5s43I03Y+HYyHBgBaSLziO2hi2kzVJccOwzBp7wS4fs1MqsFY5+IeWJ9k+hm89NiYT7+6zlEgoUMlIniny1qLqWTzx7btUeuC/y/h5TVBNgaV+z0jmHycHfeSyq5I+vmX4J8qe3wmaN8TcdqYKU5nIznOTk3CM5Fzu0Bs9vkCkOxmormmcjMFW1RbdOLc/hpZWZggsBA88sNEAI8eq+r5QEeqzeCx8YKoZDjdrsqvgLMc3El3gS9oMGxkn0Y/TEcqs9Tc4BXtTkqIA68hD0DYzlAxYjVbbkAI9Hh9lHNvV3Dr/oCkGXQ/HflM143kj1L3tSBZpqeqQE2XhngB5nqpS3OZTmZbMTQ8qD2luU18yaTGMLF5tJS/fdKPRx0gQ1kL8= diff --git a/README.md b/README.md index 85b5a0b5e8..791a99452b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![Imgur](https://i.imgur.com/w4N0yhv.png) +![Logo](core/assets/sprites/logo.png) [![Build Status](https://travis-ci.org/Anuken/Mindustry.svg?branch=master)](https://travis-ci.org/Anuken/Mindustry) [![Discord](https://img.shields.io/discord/391020510269669376.svg)](https://discord.gg/mindustry) @@ -40,6 +40,6 @@ After building, the output .JAR file should be in `/desktop/build/libs/desktop-r ### Downloads - + - + diff --git a/android/build.gradle b/android/build.gradle index 5c288d5e3a..491aaf0a5a 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -113,9 +113,11 @@ android{ } } - buildTypes{ - release{ - signingConfig signingConfigs.release + if(project.hasProperty("RELEASE_STORE_FILE")) { + buildTypes { + release { + signingConfig signingConfigs.release + } } } } diff --git a/android/src/io/anuke/mindustry/AndroidLauncher.java b/android/src/io/anuke/mindustry/AndroidLauncher.java index 3f75f746fe..28426c356d 100644 --- a/android/src/io/anuke/mindustry/AndroidLauncher.java +++ b/android/src/io/anuke/mindustry/AndroidLauncher.java @@ -146,7 +146,7 @@ public class AndroidLauncher extends AndroidApplication{ InputStream inStream; if(myFile != null) inStream = new FileInputStream(myFile); else inStream = getContentResolver().openInputStream(uri); - Core.app.post(() -> { + Core.app.post(() -> Core.app.post(() -> { if(save){ //open save System.out.println("Opening save."); FileHandle file = Core.files.local("temp-save." + saveExtension); @@ -172,7 +172,7 @@ public class AndroidLauncher extends AndroidApplication{ ui.editor.beginEditMap(file); }); } - }); + })); } }catch(IOException e){ e.printStackTrace(); diff --git a/build.gradle b/build.gradle index 15c9312444..086c056df0 100644 --- a/build.gradle +++ b/build.gradle @@ -9,7 +9,7 @@ buildscript{ dependencies{ classpath 'com.mobidevelop.robovm:robovm-gradle-plugin:2.3.6' - classpath "com.badlogicgames.gdx:gdx-tools:1.9.9" + classpath "com.badlogicgames.gdx:gdx-tools:1.9.10" classpath "com.badlogicgames.packr:packr:2.1-SNAPSHOT" } } @@ -22,7 +22,7 @@ allprojects{ versionModifier = 'beta' if(!project.hasProperty("versionType")) versionType = 'official' appName = 'Mindustry' - gdxVersion = '1.9.9' + gdxVersion = '1.9.10' roboVMVersion = '2.3.6' arcHash = null @@ -35,7 +35,7 @@ allprojects{ } getArcHash = { - //get latest commit hash from gtihub since JITPack's '-snapshot' version doesn't work correctly + //get latest commit hash from github since JITPack's '-snapshot' version doesn't work correctly if(arcHash == null){ try{ arcHash = 'git ls-remote https://github.com/Anuken/Arc.git'.execute().text.split("\t")[0] @@ -113,6 +113,8 @@ allprojects{ maven{ url 'https://jitpack.io' } jcenter() } + + tasks.withType(Javadoc).all{ enabled = false } } project(":desktop"){ @@ -132,6 +134,23 @@ project(":desktop"){ } } +project(":desktop-sdl"){ + apply plugin: "java" + + dependencies{ + compile project(":core") + compile project(":net") + + if(debugged()) compile project(":debug") + + compile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop" + compile "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-desktop" + + compile arcModule("backends:backend-sdl") + compile 'com.github.MinnDevelopment:java-discord-rpc:v2.0.2' + } +} + project(":ios"){ apply plugin: "java" apply plugin: "robovm" @@ -170,7 +189,7 @@ project(":ios"){ project(":core"){ apply plugin: "java" - task finish{ + task preGen{ generateLocales() } @@ -200,6 +219,8 @@ project(":core"){ compileJava.finalizedBy(copyGen) } + compileJava.dependsOn(preGen) + compile arcModule("arc-core") compile arcModule("extensions:freetype") compile arcModule("extensions:arcnet") @@ -242,6 +263,12 @@ project(":tools"){ dependencies{ compile project(":core") + + //for render tests + compile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop" + compile "com.badlogicgames.gdx:gdx-freetype-platform:$gdxVersion:natives-desktop" + + compile arcModule("backends:backend-sdl") } } diff --git a/core/assets-raw/sprites/blocks/defense/mend-projector-top.png b/core/assets-raw/sprites/blocks/defense/mend-projector-top.png index 217574631e..8fa8a2da3a 100644 Binary files a/core/assets-raw/sprites/blocks/defense/mend-projector-top.png and b/core/assets-raw/sprites/blocks/defense/mend-projector-top.png differ diff --git a/core/assets-raw/sprites/blocks/defense/mender-top.png b/core/assets-raw/sprites/blocks/defense/mender-top.png index 395ee6c254..36015652c7 100644 Binary files a/core/assets-raw/sprites/blocks/defense/mender-top.png and b/core/assets-raw/sprites/blocks/defense/mender-top.png differ diff --git a/core/assets-raw/sprites/blocks/defense/overdrive-projector-top.png b/core/assets-raw/sprites/blocks/defense/overdrive-projector-top.png index 9ade5fe188..83d1e772b4 100644 Binary files a/core/assets-raw/sprites/blocks/defense/overdrive-projector-top.png and b/core/assets-raw/sprites/blocks/defense/overdrive-projector-top.png differ diff --git a/core/assets-raw/sprites/blocks/distribution/bridge-arrow.png b/core/assets-raw/sprites/blocks/distribution/bridge-arrow.png new file mode 100644 index 0000000000..e478d18d76 Binary files /dev/null and b/core/assets-raw/sprites/blocks/distribution/bridge-arrow.png differ diff --git a/core/assets-raw/sprites/blocks/distribution/bridge-conveyor-arrow.png b/core/assets-raw/sprites/blocks/distribution/bridge-conveyor-arrow.png index 2c88950956..acf07f760a 100644 Binary files a/core/assets-raw/sprites/blocks/distribution/bridge-conveyor-arrow.png and b/core/assets-raw/sprites/blocks/distribution/bridge-conveyor-arrow.png differ diff --git a/core/assets-raw/sprites/blocks/distribution/bridge-conveyor-end.png b/core/assets-raw/sprites/blocks/distribution/bridge-conveyor-end.png index b553fc29a7..ccf11151c7 100644 Binary files a/core/assets-raw/sprites/blocks/distribution/bridge-conveyor-end.png and b/core/assets-raw/sprites/blocks/distribution/bridge-conveyor-end.png differ diff --git a/core/assets-raw/sprites/blocks/distribution/bridge-conveyor.png b/core/assets-raw/sprites/blocks/distribution/bridge-conveyor.png index 76b29569ea..afe8a5b17c 100644 Binary files a/core/assets-raw/sprites/blocks/distribution/bridge-conveyor.png and b/core/assets-raw/sprites/blocks/distribution/bridge-conveyor.png differ diff --git a/core/assets-raw/sprites/blocks/distribution/distributor.png b/core/assets-raw/sprites/blocks/distribution/distributor.png index 6322cb7379..4669dbc99e 100644 Binary files a/core/assets-raw/sprites/blocks/distribution/distributor.png and b/core/assets-raw/sprites/blocks/distribution/distributor.png differ diff --git a/core/assets-raw/sprites/blocks/distribution/junction.png b/core/assets-raw/sprites/blocks/distribution/junction.png index e84244e630..f973535bfb 100644 Binary files a/core/assets-raw/sprites/blocks/distribution/junction.png and b/core/assets-raw/sprites/blocks/distribution/junction.png differ diff --git a/core/assets-raw/sprites/blocks/distribution/phase-conveyor-arrow.png b/core/assets-raw/sprites/blocks/distribution/phase-conveyor-arrow.png index 5873e584e8..d514df7dfa 100644 Binary files a/core/assets-raw/sprites/blocks/distribution/phase-conveyor-arrow.png and b/core/assets-raw/sprites/blocks/distribution/phase-conveyor-arrow.png differ diff --git a/core/assets-raw/sprites/blocks/distribution/phase-conveyor.png b/core/assets-raw/sprites/blocks/distribution/phase-conveyor.png index 20c9739180..e2fca93c08 100644 Binary files a/core/assets-raw/sprites/blocks/distribution/phase-conveyor.png and b/core/assets-raw/sprites/blocks/distribution/phase-conveyor.png differ diff --git a/core/assets-raw/sprites/blocks/distribution/router.png b/core/assets-raw/sprites/blocks/distribution/router.png index 59a5fa0564..61201a705a 100644 Binary files a/core/assets-raw/sprites/blocks/distribution/router.png and b/core/assets-raw/sprites/blocks/distribution/router.png differ diff --git a/core/assets-raw/sprites/blocks/drills/blast-drill-rim.png b/core/assets-raw/sprites/blocks/drills/blast-drill-rim.png index dc6cb23e0f..b71305c856 100644 Binary files a/core/assets-raw/sprites/blocks/drills/blast-drill-rim.png and b/core/assets-raw/sprites/blocks/drills/blast-drill-rim.png differ diff --git a/core/assets-raw/sprites/blocks/drills/blast-drill-rotator.png b/core/assets-raw/sprites/blocks/drills/blast-drill-rotator.png index ab75a38dd0..98a2834240 100644 Binary files a/core/assets-raw/sprites/blocks/drills/blast-drill-rotator.png and b/core/assets-raw/sprites/blocks/drills/blast-drill-rotator.png differ diff --git a/core/assets-raw/sprites/blocks/drills/blast-drill-top.png b/core/assets-raw/sprites/blocks/drills/blast-drill-top.png index 3448ea9e70..189c04a372 100644 Binary files a/core/assets-raw/sprites/blocks/drills/blast-drill-top.png and b/core/assets-raw/sprites/blocks/drills/blast-drill-top.png differ diff --git a/core/assets-raw/sprites/blocks/drills/blast-drill.png b/core/assets-raw/sprites/blocks/drills/blast-drill.png index fcb9c57a1e..18697e720f 100644 Binary files a/core/assets-raw/sprites/blocks/drills/blast-drill.png and b/core/assets-raw/sprites/blocks/drills/blast-drill.png differ diff --git a/core/assets-raw/sprites/blocks/drills/laser-drill-rim.png b/core/assets-raw/sprites/blocks/drills/laser-drill-rim.png index 45d006600c..3db73498f5 100644 Binary files a/core/assets-raw/sprites/blocks/drills/laser-drill-rim.png and b/core/assets-raw/sprites/blocks/drills/laser-drill-rim.png differ diff --git a/core/assets-raw/sprites/blocks/drills/laser-drill-rotator.png b/core/assets-raw/sprites/blocks/drills/laser-drill-rotator.png index d4cf0ec730..44aa88d6b8 100644 Binary files a/core/assets-raw/sprites/blocks/drills/laser-drill-rotator.png and b/core/assets-raw/sprites/blocks/drills/laser-drill-rotator.png differ diff --git a/core/assets-raw/sprites/blocks/drills/laser-drill-top.png b/core/assets-raw/sprites/blocks/drills/laser-drill-top.png index 1b45be8083..bc2c136aea 100644 Binary files a/core/assets-raw/sprites/blocks/drills/laser-drill-top.png and b/core/assets-raw/sprites/blocks/drills/laser-drill-top.png differ diff --git a/core/assets-raw/sprites/blocks/drills/laser-drill.png b/core/assets-raw/sprites/blocks/drills/laser-drill.png index b183f080d3..95cbc0a8e0 100644 Binary files a/core/assets-raw/sprites/blocks/drills/laser-drill.png and b/core/assets-raw/sprites/blocks/drills/laser-drill.png differ diff --git a/core/assets-raw/sprites/blocks/drills/mechanical-drill-top.png b/core/assets-raw/sprites/blocks/drills/mechanical-drill-top.png index 6cbbd821fd..3c38f1b6ad 100644 Binary files a/core/assets-raw/sprites/blocks/drills/mechanical-drill-top.png and b/core/assets-raw/sprites/blocks/drills/mechanical-drill-top.png differ diff --git a/core/assets-raw/sprites/blocks/drills/oil-extractor-rotator.png b/core/assets-raw/sprites/blocks/drills/oil-extractor-rotator.png index ced2a08d0e..a076b412c0 100644 Binary files a/core/assets-raw/sprites/blocks/drills/oil-extractor-rotator.png and b/core/assets-raw/sprites/blocks/drills/oil-extractor-rotator.png differ diff --git a/core/assets-raw/sprites/blocks/drills/oil-extractor-top.png b/core/assets-raw/sprites/blocks/drills/oil-extractor-top.png index f9c9008ed0..fd1d1046a2 100644 Binary files a/core/assets-raw/sprites/blocks/drills/oil-extractor-top.png and b/core/assets-raw/sprites/blocks/drills/oil-extractor-top.png differ diff --git a/core/assets-raw/sprites/blocks/drills/oil-extractor.png b/core/assets-raw/sprites/blocks/drills/oil-extractor.png index 08af487136..8568a087e4 100644 Binary files a/core/assets-raw/sprites/blocks/drills/oil-extractor.png and b/core/assets-raw/sprites/blocks/drills/oil-extractor.png differ diff --git a/core/assets-raw/sprites/blocks/drills/pneumatic-drill-rotator.png b/core/assets-raw/sprites/blocks/drills/pneumatic-drill-rotator.png index 98ab08b0ea..b9b498872d 100644 Binary files a/core/assets-raw/sprites/blocks/drills/pneumatic-drill-rotator.png and b/core/assets-raw/sprites/blocks/drills/pneumatic-drill-rotator.png differ diff --git a/core/assets-raw/sprites/blocks/drills/pneumatic-drill-top.png b/core/assets-raw/sprites/blocks/drills/pneumatic-drill-top.png index 7d9e100498..6b9dd1f20e 100644 Binary files a/core/assets-raw/sprites/blocks/drills/pneumatic-drill-top.png and b/core/assets-raw/sprites/blocks/drills/pneumatic-drill-top.png differ diff --git a/core/assets-raw/sprites/blocks/drills/pneumatic-drill.png b/core/assets-raw/sprites/blocks/drills/pneumatic-drill.png index a265034fef..05e6832c37 100644 Binary files a/core/assets-raw/sprites/blocks/drills/pneumatic-drill.png and b/core/assets-raw/sprites/blocks/drills/pneumatic-drill.png differ diff --git a/core/assets-raw/sprites/blocks/drills/water-extractor-liquid.png b/core/assets-raw/sprites/blocks/drills/water-extractor-liquid.png index 0c48f91821..2ac1564812 100644 Binary files a/core/assets-raw/sprites/blocks/drills/water-extractor-liquid.png and b/core/assets-raw/sprites/blocks/drills/water-extractor-liquid.png differ diff --git a/core/assets-raw/sprites/blocks/drills/water-extractor-top.png b/core/assets-raw/sprites/blocks/drills/water-extractor-top.png index 96e7c4482b..088e510dc5 100644 Binary files a/core/assets-raw/sprites/blocks/drills/water-extractor-top.png and b/core/assets-raw/sprites/blocks/drills/water-extractor-top.png differ diff --git a/core/assets-raw/sprites/blocks/drills/water-extractor.png b/core/assets-raw/sprites/blocks/drills/water-extractor.png index 1a0a42382c..61030e7560 100644 Binary files a/core/assets-raw/sprites/blocks/drills/water-extractor.png and b/core/assets-raw/sprites/blocks/drills/water-extractor.png differ diff --git a/core/assets-raw/sprites/blocks/environment/cliffs1.png b/core/assets-raw/sprites/blocks/environment/cliffs1.png index 52b99e2de6..087e3065e2 100644 Binary files a/core/assets-raw/sprites/blocks/environment/cliffs1.png and b/core/assets-raw/sprites/blocks/environment/cliffs1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/dark-metal-large.png b/core/assets-raw/sprites/blocks/environment/dark-metal-large.png index 2b30255f53..427eecae3c 100644 Binary files a/core/assets-raw/sprites/blocks/environment/dark-metal-large.png and b/core/assets-raw/sprites/blocks/environment/dark-metal-large.png differ diff --git a/core/assets-raw/sprites/blocks/environment/ice-snow1.png b/core/assets-raw/sprites/blocks/environment/ice-snow1.png index d671587375..fa26a7eb94 100644 Binary files a/core/assets-raw/sprites/blocks/environment/ice-snow1.png and b/core/assets-raw/sprites/blocks/environment/ice-snow1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/ice-snow2.png b/core/assets-raw/sprites/blocks/environment/ice-snow2.png index 115a8a08a2..b1b895af0a 100644 Binary files a/core/assets-raw/sprites/blocks/environment/ice-snow2.png and b/core/assets-raw/sprites/blocks/environment/ice-snow2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/ice-snow3.png b/core/assets-raw/sprites/blocks/environment/ice-snow3.png index 944fb54588..6448172835 100644 Binary files a/core/assets-raw/sprites/blocks/environment/ice-snow3.png and b/core/assets-raw/sprites/blocks/environment/ice-snow3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/icerocks-large.png b/core/assets-raw/sprites/blocks/environment/icerocks-large.png index 4a9ffd8e52..f43c40e61a 100644 Binary files a/core/assets-raw/sprites/blocks/environment/icerocks-large.png and b/core/assets-raw/sprites/blocks/environment/icerocks-large.png differ diff --git a/core/assets-raw/sprites/blocks/environment/icerocks1.png b/core/assets-raw/sprites/blocks/environment/icerocks1.png index 8e11fd1ddf..8b93485477 100644 Binary files a/core/assets-raw/sprites/blocks/environment/icerocks1.png and b/core/assets-raw/sprites/blocks/environment/icerocks1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/icerocks2.png b/core/assets-raw/sprites/blocks/environment/icerocks2.png index 9b2cd18d2f..7264d6aa03 100644 Binary files a/core/assets-raw/sprites/blocks/environment/icerocks2.png and b/core/assets-raw/sprites/blocks/environment/icerocks2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/pebbles1.png b/core/assets-raw/sprites/blocks/environment/pebbles1.png index 81baa64bd5..cac9429ba0 100644 Binary files a/core/assets-raw/sprites/blocks/environment/pebbles1.png and b/core/assets-raw/sprites/blocks/environment/pebbles1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/pebbles2.png b/core/assets-raw/sprites/blocks/environment/pebbles2.png index 7b11d5fc17..a909715845 100644 Binary files a/core/assets-raw/sprites/blocks/environment/pebbles2.png and b/core/assets-raw/sprites/blocks/environment/pebbles2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/pebbles3.png b/core/assets-raw/sprites/blocks/environment/pebbles3.png index 39b1ebd9c5..b8585099aa 100644 Binary files a/core/assets-raw/sprites/blocks/environment/pebbles3.png and b/core/assets-raw/sprites/blocks/environment/pebbles3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/pine.png b/core/assets-raw/sprites/blocks/environment/pine.png index 1642bbbfd0..8a4dcd9ad2 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/rock1.png b/core/assets-raw/sprites/blocks/environment/rock1.png index f5fbeae6eb..75d81ad163 100644 Binary files a/core/assets-raw/sprites/blocks/environment/rock1.png and b/core/assets-raw/sprites/blocks/environment/rock1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/rock2.png b/core/assets-raw/sprites/blocks/environment/rock2.png index df9303897d..b4a900c4fd 100644 Binary files a/core/assets-raw/sprites/blocks/environment/rock2.png and b/core/assets-raw/sprites/blocks/environment/rock2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/saltrocks-large.png b/core/assets-raw/sprites/blocks/environment/saltrocks-large.png index f0ec9c74f3..3bf4af2ec1 100644 Binary files a/core/assets-raw/sprites/blocks/environment/saltrocks-large.png and b/core/assets-raw/sprites/blocks/environment/saltrocks-large.png differ diff --git a/core/assets-raw/sprites/blocks/environment/saltrocks1.png b/core/assets-raw/sprites/blocks/environment/saltrocks1.png index 5ad770404e..74045a27a7 100644 Binary files a/core/assets-raw/sprites/blocks/environment/saltrocks1.png and b/core/assets-raw/sprites/blocks/environment/saltrocks1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/saltrocks2.png b/core/assets-raw/sprites/blocks/environment/saltrocks2.png index b44d62eba4..25b801e550 100644 Binary files a/core/assets-raw/sprites/blocks/environment/saltrocks2.png and b/core/assets-raw/sprites/blocks/environment/saltrocks2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/sand-boulder1.png b/core/assets-raw/sprites/blocks/environment/sand-boulder1.png new file mode 100644 index 0000000000..4afe994648 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/sand-boulder1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/sand-boulder2.png b/core/assets-raw/sprites/blocks/environment/sand-boulder2.png new file mode 100644 index 0000000000..3c59c6240e Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/sand-boulder2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/sand1.png b/core/assets-raw/sprites/blocks/environment/sand1.png index ae4fe3c363..ae6ca2d3be 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/sandrocks-large.png b/core/assets-raw/sprites/blocks/environment/sandrocks-large.png index ff3efd9395..e9148b71b9 100644 Binary files a/core/assets-raw/sprites/blocks/environment/sandrocks-large.png 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 index 2217bbd5e0..55f9afbbd5 100644 Binary files a/core/assets-raw/sprites/blocks/environment/sandrocks1.png 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 index b2dacd5abf..2078ee2f2d 100644 Binary files a/core/assets-raw/sprites/blocks/environment/sandrocks2.png and b/core/assets-raw/sprites/blocks/environment/sandrocks2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/shale-boulder1.png b/core/assets-raw/sprites/blocks/environment/shale-boulder1.png index ed47edab22..00cc2f2ccb 100644 Binary files a/core/assets-raw/sprites/blocks/environment/shale-boulder1.png and b/core/assets-raw/sprites/blocks/environment/shale-boulder1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/shale-boulder2.png b/core/assets-raw/sprites/blocks/environment/shale-boulder2.png index 1d54fe6d4a..e03c20b62c 100644 Binary files a/core/assets-raw/sprites/blocks/environment/shale-boulder2.png and b/core/assets-raw/sprites/blocks/environment/shale-boulder2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/shalerocks1.png b/core/assets-raw/sprites/blocks/environment/shalerocks1.png index f489ee1d03..ff8b482bb7 100644 Binary files a/core/assets-raw/sprites/blocks/environment/shalerocks1.png and b/core/assets-raw/sprites/blocks/environment/shalerocks1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/shalerocks2.png b/core/assets-raw/sprites/blocks/environment/shalerocks2.png index 356255acb4..50d0f74c0c 100644 Binary files a/core/assets-raw/sprites/blocks/environment/shalerocks2.png and b/core/assets-raw/sprites/blocks/environment/shalerocks2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/snow-pine.png b/core/assets-raw/sprites/blocks/environment/snow-pine.png new file mode 100644 index 0000000000..3e6f6a9da0 Binary files /dev/null and b/core/assets-raw/sprites/blocks/environment/snow-pine.png differ diff --git a/core/assets-raw/sprites/blocks/environment/snowrock1.png b/core/assets-raw/sprites/blocks/environment/snowrock1.png index 5c3a702ccd..d81d328b9c 100644 Binary files a/core/assets-raw/sprites/blocks/environment/snowrock1.png and b/core/assets-raw/sprites/blocks/environment/snowrock1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/snowrock2.png b/core/assets-raw/sprites/blocks/environment/snowrock2.png index c25c544910..99a4b14ce0 100644 Binary files a/core/assets-raw/sprites/blocks/environment/snowrock2.png and b/core/assets-raw/sprites/blocks/environment/snowrock2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/snowrocks-large.png b/core/assets-raw/sprites/blocks/environment/snowrocks-large.png index 01cfa406f8..eb0a0f8ad8 100644 Binary files a/core/assets-raw/sprites/blocks/environment/snowrocks-large.png and b/core/assets-raw/sprites/blocks/environment/snowrocks-large.png differ diff --git a/core/assets-raw/sprites/blocks/environment/snowrocks1.png b/core/assets-raw/sprites/blocks/environment/snowrocks1.png index 32bb74348d..c61d6f7f9e 100644 Binary files a/core/assets-raw/sprites/blocks/environment/snowrocks1.png and b/core/assets-raw/sprites/blocks/environment/snowrocks1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/snowrocks2.png b/core/assets-raw/sprites/blocks/environment/snowrocks2.png index 8ddeafa1ff..3d659efc32 100644 Binary files a/core/assets-raw/sprites/blocks/environment/snowrocks2.png and b/core/assets-raw/sprites/blocks/environment/snowrocks2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/spore-cluster1.png b/core/assets-raw/sprites/blocks/environment/spore-cluster1.png index 9e3738039b..9bfdd4a4d2 100644 Binary files a/core/assets-raw/sprites/blocks/environment/spore-cluster1.png and b/core/assets-raw/sprites/blocks/environment/spore-cluster1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/spore-cluster2.png b/core/assets-raw/sprites/blocks/environment/spore-cluster2.png index 4aaa8d86e3..4696b76ed9 100644 Binary files a/core/assets-raw/sprites/blocks/environment/spore-cluster2.png and b/core/assets-raw/sprites/blocks/environment/spore-cluster2.png differ diff --git a/core/assets-raw/sprites/blocks/environment/spore-cluster3.png b/core/assets-raw/sprites/blocks/environment/spore-cluster3.png index 57462c7762..047cada29a 100644 Binary files a/core/assets-raw/sprites/blocks/environment/spore-cluster3.png and b/core/assets-raw/sprites/blocks/environment/spore-cluster3.png differ diff --git a/core/assets-raw/sprites/blocks/environment/spore-pine.png b/core/assets-raw/sprites/blocks/environment/spore-pine.png index 661c4caeb7..802248118a 100644 Binary files a/core/assets-raw/sprites/blocks/environment/spore-pine.png and b/core/assets-raw/sprites/blocks/environment/spore-pine.png differ diff --git a/core/assets-raw/sprites/blocks/environment/sporerocks-large.png b/core/assets-raw/sprites/blocks/environment/sporerocks-large.png index 4153ac2798..d02f83cdff 100644 Binary files a/core/assets-raw/sprites/blocks/environment/sporerocks-large.png and b/core/assets-raw/sprites/blocks/environment/sporerocks-large.png differ diff --git a/core/assets-raw/sprites/blocks/environment/sporerocks1.png b/core/assets-raw/sprites/blocks/environment/sporerocks1.png index 9672003dfb..6f937d4613 100644 Binary files a/core/assets-raw/sprites/blocks/environment/sporerocks1.png and b/core/assets-raw/sprites/blocks/environment/sporerocks1.png differ diff --git a/core/assets-raw/sprites/blocks/environment/sporerocks2.png b/core/assets-raw/sprites/blocks/environment/sporerocks2.png index 668e3d2cc6..cebda293b9 100644 Binary files a/core/assets-raw/sprites/blocks/environment/sporerocks2.png and b/core/assets-raw/sprites/blocks/environment/sporerocks2.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/bridge-conduit-arrow.png b/core/assets-raw/sprites/blocks/liquid/bridge-conduit-arrow.png index 2c88950956..05bb28604f 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/bridge-conduit-arrow.png and b/core/assets-raw/sprites/blocks/liquid/bridge-conduit-arrow.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/bridge-conduit-end.png b/core/assets-raw/sprites/blocks/liquid/bridge-conduit-end.png index 4fe3d03201..1142e49e21 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/bridge-conduit-end.png and b/core/assets-raw/sprites/blocks/liquid/bridge-conduit-end.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/bridge-conduit.png b/core/assets-raw/sprites/blocks/liquid/bridge-conduit.png index 6b10c50140..f1c7bc3055 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/bridge-conduit.png and b/core/assets-raw/sprites/blocks/liquid/bridge-conduit.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/conduit-bottom-1.png b/core/assets-raw/sprites/blocks/liquid/conduit-bottom-1.png index 7153704def..88e4f28423 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/conduit-bottom-1.png and b/core/assets-raw/sprites/blocks/liquid/conduit-bottom-1.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/conduit-bottom-2.png b/core/assets-raw/sprites/blocks/liquid/conduit-bottom-2.png index 7d5b6fb9f9..3c968dd2b4 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/conduit-bottom-2.png and b/core/assets-raw/sprites/blocks/liquid/conduit-bottom-2.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/conduit-bottom-3.png b/core/assets-raw/sprites/blocks/liquid/conduit-bottom-3.png index 977188d577..6b0a4ffff9 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/conduit-bottom-3.png and b/core/assets-raw/sprites/blocks/liquid/conduit-bottom-3.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/conduit-bottom-4.png b/core/assets-raw/sprites/blocks/liquid/conduit-bottom-4.png index 0328b79b3e..969b593d8e 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/conduit-bottom-4.png and b/core/assets-raw/sprites/blocks/liquid/conduit-bottom-4.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/conduit-bottom-5.png b/core/assets-raw/sprites/blocks/liquid/conduit-bottom-5.png index e7ef35006f..0317e0b0fa 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/conduit-bottom-5.png and b/core/assets-raw/sprites/blocks/liquid/conduit-bottom-5.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/conduit-bottom-6.png b/core/assets-raw/sprites/blocks/liquid/conduit-bottom-6.png index 9b4b292794..30ecffba39 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/conduit-bottom-6.png and b/core/assets-raw/sprites/blocks/liquid/conduit-bottom-6.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/conduit-bottom.png b/core/assets-raw/sprites/blocks/liquid/conduit-bottom.png index 4908fa83c9..1390737d20 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/conduit-bottom.png and b/core/assets-raw/sprites/blocks/liquid/conduit-bottom.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/conduit-top-0.png b/core/assets-raw/sprites/blocks/liquid/conduit-top-0.png index 9dc9384971..a9dc2ec9c8 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/conduit-top-0.png and b/core/assets-raw/sprites/blocks/liquid/conduit-top-0.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/conduit-top-1.png b/core/assets-raw/sprites/blocks/liquid/conduit-top-1.png index e219a5751d..d223e31491 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/conduit-top-1.png and b/core/assets-raw/sprites/blocks/liquid/conduit-top-1.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/conduit-top-2.png b/core/assets-raw/sprites/blocks/liquid/conduit-top-2.png index 30d039d2d8..c29c2fc1e2 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/conduit-top-2.png and b/core/assets-raw/sprites/blocks/liquid/conduit-top-2.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/conduit-top-3.png b/core/assets-raw/sprites/blocks/liquid/conduit-top-3.png index c7feafdfa8..c5500f1fd3 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/conduit-top-3.png and b/core/assets-raw/sprites/blocks/liquid/conduit-top-3.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/conduit-top-4.png b/core/assets-raw/sprites/blocks/liquid/conduit-top-4.png index 58ab8e6927..ba4bc1c99a 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/conduit-top-4.png and b/core/assets-raw/sprites/blocks/liquid/conduit-top-4.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/conduit-top-5.png b/core/assets-raw/sprites/blocks/liquid/conduit-top-5.png index 72461ba0b6..debece9dc9 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/conduit-top-5.png and b/core/assets-raw/sprites/blocks/liquid/conduit-top-5.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/conduit-top-6.png b/core/assets-raw/sprites/blocks/liquid/conduit-top-6.png index d30fc7a8b6..56976bfe14 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/conduit-top-6.png and b/core/assets-raw/sprites/blocks/liquid/conduit-top-6.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/liquid-junction.png b/core/assets-raw/sprites/blocks/liquid/liquid-junction.png index 0b0ad5344d..737f148b04 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/liquid-junction.png and b/core/assets-raw/sprites/blocks/liquid/liquid-junction.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/liquid-router-bottom.png b/core/assets-raw/sprites/blocks/liquid/liquid-router-bottom.png index 75b058a987..be9e88c572 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/liquid-router-bottom.png and b/core/assets-raw/sprites/blocks/liquid/liquid-router-bottom.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/liquid-router-liquid.png b/core/assets-raw/sprites/blocks/liquid/liquid-router-liquid.png index a32ca6161a..09957a6554 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/liquid-router-liquid.png and b/core/assets-raw/sprites/blocks/liquid/liquid-router-liquid.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/liquid-router-top.png b/core/assets-raw/sprites/blocks/liquid/liquid-router-top.png index 53e880b826..474a4ecac8 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/liquid-router-top.png and b/core/assets-raw/sprites/blocks/liquid/liquid-router-top.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/phase-conduit-arrow.png b/core/assets-raw/sprites/blocks/liquid/phase-conduit-arrow.png index 858a02861c..a1a0cefc09 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/phase-conduit-arrow.png and b/core/assets-raw/sprites/blocks/liquid/phase-conduit-arrow.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/phase-conduit.png b/core/assets-raw/sprites/blocks/liquid/phase-conduit.png index 9443960074..1956ea3565 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/phase-conduit.png and b/core/assets-raw/sprites/blocks/liquid/phase-conduit.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/pulse-conduit-top-0.png b/core/assets-raw/sprites/blocks/liquid/pulse-conduit-top-0.png index c6a453fed9..8ae31a2dbc 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/pulse-conduit-top-0.png and b/core/assets-raw/sprites/blocks/liquid/pulse-conduit-top-0.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/pulse-conduit-top-1.png b/core/assets-raw/sprites/blocks/liquid/pulse-conduit-top-1.png index 62f03471c4..f86fde1240 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/pulse-conduit-top-1.png and b/core/assets-raw/sprites/blocks/liquid/pulse-conduit-top-1.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/pulse-conduit-top-2.png b/core/assets-raw/sprites/blocks/liquid/pulse-conduit-top-2.png index 3cea1a8e8d..2d9bcb39a3 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/pulse-conduit-top-2.png and b/core/assets-raw/sprites/blocks/liquid/pulse-conduit-top-2.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/pulse-conduit-top-3.png b/core/assets-raw/sprites/blocks/liquid/pulse-conduit-top-3.png index 657e292eeb..d625cd185b 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/pulse-conduit-top-3.png and b/core/assets-raw/sprites/blocks/liquid/pulse-conduit-top-3.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/pulse-conduit-top-4.png b/core/assets-raw/sprites/blocks/liquid/pulse-conduit-top-4.png index 0dda362ff1..e1938fde0b 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/pulse-conduit-top-4.png and b/core/assets-raw/sprites/blocks/liquid/pulse-conduit-top-4.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/pulse-conduit-top-5.png b/core/assets-raw/sprites/blocks/liquid/pulse-conduit-top-5.png index 7ada32da91..ed9d334798 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/pulse-conduit-top-5.png and b/core/assets-raw/sprites/blocks/liquid/pulse-conduit-top-5.png differ diff --git a/core/assets-raw/sprites/blocks/liquid/pulse-conduit-top-6.png b/core/assets-raw/sprites/blocks/liquid/pulse-conduit-top-6.png index f43d03fa16..f25158d7de 100644 Binary files a/core/assets-raw/sprites/blocks/liquid/pulse-conduit-top-6.png and b/core/assets-raw/sprites/blocks/liquid/pulse-conduit-top-6.png differ diff --git a/core/assets-raw/sprites/blocks/power/battery-large.png b/core/assets-raw/sprites/blocks/power/battery-large.png index 5f7d9afc2c..5917051f44 100644 Binary files a/core/assets-raw/sprites/blocks/power/battery-large.png and b/core/assets-raw/sprites/blocks/power/battery-large.png differ diff --git a/core/assets-raw/sprites/blocks/power/battery.png b/core/assets-raw/sprites/blocks/power/battery.png index 65593f2167..44a863f123 100644 Binary files a/core/assets-raw/sprites/blocks/power/battery.png and b/core/assets-raw/sprites/blocks/power/battery.png differ diff --git a/core/assets-raw/sprites/blocks/power/differential-generator-liquid.png b/core/assets-raw/sprites/blocks/power/differential-generator-liquid.png new file mode 100644 index 0000000000..fa68927de4 Binary files /dev/null and b/core/assets-raw/sprites/blocks/power/differential-generator-liquid.png differ diff --git a/core/assets-raw/sprites/blocks/power/differential-generator.png b/core/assets-raw/sprites/blocks/power/differential-generator.png index 96ff71e8ac..01a271abe0 100644 Binary files a/core/assets-raw/sprites/blocks/power/differential-generator.png and b/core/assets-raw/sprites/blocks/power/differential-generator.png differ diff --git a/core/assets-raw/sprites/blocks/power/impact-reactor-bottom.png b/core/assets-raw/sprites/blocks/power/impact-reactor-bottom.png index 8275642a0f..6b16fca94c 100644 Binary files a/core/assets-raw/sprites/blocks/power/impact-reactor-bottom.png and b/core/assets-raw/sprites/blocks/power/impact-reactor-bottom.png differ diff --git a/core/assets-raw/sprites/blocks/power/impact-reactor-top.png b/core/assets-raw/sprites/blocks/power/impact-reactor-top.png deleted file mode 100644 index ee89e87b5e..0000000000 Binary files a/core/assets-raw/sprites/blocks/power/impact-reactor-top.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/power/impact-reactor.png b/core/assets-raw/sprites/blocks/power/impact-reactor.png index 89bb2b8ca5..c1dd5e46c8 100644 Binary files a/core/assets-raw/sprites/blocks/power/impact-reactor.png and b/core/assets-raw/sprites/blocks/power/impact-reactor.png differ diff --git a/core/assets-raw/sprites/blocks/power/power-node-large.png b/core/assets-raw/sprites/blocks/power/power-node-large.png index 0a76d7e1a7..add53dd280 100644 Binary files a/core/assets-raw/sprites/blocks/power/power-node-large.png and b/core/assets-raw/sprites/blocks/power/power-node-large.png differ diff --git a/core/assets-raw/sprites/blocks/power/power-node.png b/core/assets-raw/sprites/blocks/power/power-node.png index 0e7296b98f..e8f6498ee1 100644 Binary files a/core/assets-raw/sprites/blocks/power/power-node.png and b/core/assets-raw/sprites/blocks/power/power-node.png differ diff --git a/core/assets-raw/sprites/blocks/power/rtg-generator-top.png b/core/assets-raw/sprites/blocks/power/rtg-generator-top.png index f4b6d38c54..dc89fca155 100644 Binary files a/core/assets-raw/sprites/blocks/power/rtg-generator-top.png and b/core/assets-raw/sprites/blocks/power/rtg-generator-top.png differ diff --git a/core/assets-raw/sprites/blocks/power/rtg-generator.png b/core/assets-raw/sprites/blocks/power/rtg-generator.png index bb33034b49..414a606c8c 100644 Binary files a/core/assets-raw/sprites/blocks/power/rtg-generator.png and b/core/assets-raw/sprites/blocks/power/rtg-generator.png differ diff --git a/core/assets-raw/sprites/blocks/power/surge-tower.png b/core/assets-raw/sprites/blocks/power/surge-tower.png index ec9ab71c70..f381af0813 100644 Binary files a/core/assets-raw/sprites/blocks/power/surge-tower.png and b/core/assets-raw/sprites/blocks/power/surge-tower.png differ diff --git a/core/assets-raw/sprites/blocks/power/thermal-generator.png b/core/assets-raw/sprites/blocks/power/thermal-generator.png index b0ad9dc496..07b1da1567 100644 Binary files a/core/assets-raw/sprites/blocks/power/thermal-generator.png and b/core/assets-raw/sprites/blocks/power/thermal-generator.png differ diff --git a/core/assets-raw/sprites/blocks/power/thorium-reactor-center.png b/core/assets-raw/sprites/blocks/power/thorium-reactor-center.png index 10afc2e244..1254159ab9 100644 Binary files a/core/assets-raw/sprites/blocks/power/thorium-reactor-center.png and b/core/assets-raw/sprites/blocks/power/thorium-reactor-center.png differ diff --git a/core/assets-raw/sprites/blocks/power/thorium-reactor-lights.png b/core/assets-raw/sprites/blocks/power/thorium-reactor-lights.png index 2bc7d1baab..fe7b76179c 100644 Binary files a/core/assets-raw/sprites/blocks/power/thorium-reactor-lights.png and b/core/assets-raw/sprites/blocks/power/thorium-reactor-lights.png differ diff --git a/core/assets-raw/sprites/blocks/power/thorium-reactor.png b/core/assets-raw/sprites/blocks/power/thorium-reactor.png index 3d8ed983b0..7b7fdc1c79 100644 Binary files a/core/assets-raw/sprites/blocks/power/thorium-reactor.png and b/core/assets-raw/sprites/blocks/power/thorium-reactor.png differ diff --git a/core/assets-raw/sprites/blocks/power/turbine-generator-liquid.png b/core/assets-raw/sprites/blocks/power/turbine-generator-liquid.png new file mode 100644 index 0000000000..e083c04492 Binary files /dev/null and b/core/assets-raw/sprites/blocks/power/turbine-generator-liquid.png differ diff --git a/core/assets-raw/sprites/blocks/power/turbine-generator-top.png b/core/assets-raw/sprites/blocks/power/turbine-generator-top.png index c95d49851a..d7cf0d8547 100644 Binary files a/core/assets-raw/sprites/blocks/power/turbine-generator-top.png and b/core/assets-raw/sprites/blocks/power/turbine-generator-top.png differ diff --git a/core/assets-raw/sprites/blocks/power/turbine-generator.png b/core/assets-raw/sprites/blocks/power/turbine-generator.png index aa302411ee..b434c5c6fa 100644 Binary files a/core/assets-raw/sprites/blocks/power/turbine-generator.png and b/core/assets-raw/sprites/blocks/power/turbine-generator.png differ diff --git a/core/assets-raw/sprites/blocks/production/alloy-smelter-top.png b/core/assets-raw/sprites/blocks/production/alloy-smelter-top.png index aa106fffa3..c946c0dd3e 100644 Binary files a/core/assets-raw/sprites/blocks/production/alloy-smelter-top.png and b/core/assets-raw/sprites/blocks/production/alloy-smelter-top.png differ diff --git a/core/assets-raw/sprites/blocks/production/cryofluidmixer-liquid.png b/core/assets-raw/sprites/blocks/production/cryofluidmixer-liquid.png index a7a0aa14af..929c629499 100644 Binary files a/core/assets-raw/sprites/blocks/production/cryofluidmixer-liquid.png and b/core/assets-raw/sprites/blocks/production/cryofluidmixer-liquid.png differ diff --git a/core/assets-raw/sprites/blocks/production/graphite-press.png b/core/assets-raw/sprites/blocks/production/graphite-press.png index b4d7a2e255..39d6adbe36 100644 Binary files a/core/assets-raw/sprites/blocks/production/graphite-press.png and b/core/assets-raw/sprites/blocks/production/graphite-press.png differ diff --git a/core/assets-raw/sprites/blocks/production/melter.png b/core/assets-raw/sprites/blocks/production/melter.png index 7502a32e17..2f4c3a0500 100644 Binary files a/core/assets-raw/sprites/blocks/production/melter.png and b/core/assets-raw/sprites/blocks/production/melter.png differ diff --git a/core/assets-raw/sprites/blocks/production/pump-liquid.png b/core/assets-raw/sprites/blocks/production/pump-liquid.png index f53fd4f8f4..e3d4c58e55 100644 Binary files a/core/assets-raw/sprites/blocks/production/pump-liquid.png and b/core/assets-raw/sprites/blocks/production/pump-liquid.png differ diff --git a/core/assets-raw/sprites/blocks/production/separator-liquid.png b/core/assets-raw/sprites/blocks/production/separator-liquid.png index af231fedb5..f9adfeb523 100644 Binary files a/core/assets-raw/sprites/blocks/production/separator-liquid.png and b/core/assets-raw/sprites/blocks/production/separator-liquid.png differ diff --git a/core/assets-raw/sprites/blocks/production/spore-press-liquid.png b/core/assets-raw/sprites/blocks/production/spore-press-liquid.png index b6ee31e12a..63944ceee2 100644 Binary files a/core/assets-raw/sprites/blocks/production/spore-press-liquid.png and b/core/assets-raw/sprites/blocks/production/spore-press-liquid.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/arc.png b/core/assets-raw/sprites/blocks/turrets/arc.png index 5231db0265..b90265b520 100644 Binary files a/core/assets-raw/sprites/blocks/turrets/arc.png and b/core/assets-raw/sprites/blocks/turrets/arc.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/bases/block-1.png b/core/assets-raw/sprites/blocks/turrets/bases/block-1.png index 43a8576c0f..36ec5be9a8 100644 Binary files a/core/assets-raw/sprites/blocks/turrets/bases/block-1.png and b/core/assets-raw/sprites/blocks/turrets/bases/block-1.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/bases/block-2.png b/core/assets-raw/sprites/blocks/turrets/bases/block-2.png index b425980c32..ec0fba351a 100644 Binary files a/core/assets-raw/sprites/blocks/turrets/bases/block-2.png and b/core/assets-raw/sprites/blocks/turrets/bases/block-2.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/bases/block-3.png b/core/assets-raw/sprites/blocks/turrets/bases/block-3.png index 4997c7fc3e..1b01ddd33f 100644 Binary files a/core/assets-raw/sprites/blocks/turrets/bases/block-3.png and b/core/assets-raw/sprites/blocks/turrets/bases/block-3.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/bases/block-4.png b/core/assets-raw/sprites/blocks/turrets/bases/block-4.png index 7206b69d95..0cf01f72a9 100644 Binary files a/core/assets-raw/sprites/blocks/turrets/bases/block-4.png and b/core/assets-raw/sprites/blocks/turrets/bases/block-4.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/cyclone.png b/core/assets-raw/sprites/blocks/turrets/cyclone.png index 84d62394dc..e2f0dbbfcb 100644 Binary files a/core/assets-raw/sprites/blocks/turrets/cyclone.png and b/core/assets-raw/sprites/blocks/turrets/cyclone.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/fuse.png b/core/assets-raw/sprites/blocks/turrets/fuse.png index d142523a22..39fedd6b51 100644 Binary files a/core/assets-raw/sprites/blocks/turrets/fuse.png and b/core/assets-raw/sprites/blocks/turrets/fuse.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/hail.png b/core/assets-raw/sprites/blocks/turrets/hail.png index 77aa236fa3..ffa58615d2 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/lancer.png b/core/assets-raw/sprites/blocks/turrets/lancer.png index 2a998ac328..60f667d960 100644 Binary files a/core/assets-raw/sprites/blocks/turrets/lancer.png and b/core/assets-raw/sprites/blocks/turrets/lancer.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/meltdown.png b/core/assets-raw/sprites/blocks/turrets/meltdown.png index 1d0b7aba73..824443f1d5 100644 Binary files a/core/assets-raw/sprites/blocks/turrets/meltdown.png and b/core/assets-raw/sprites/blocks/turrets/meltdown.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/ripple.png b/core/assets-raw/sprites/blocks/turrets/ripple.png index 0dddade4fc..9013b07a94 100644 Binary files a/core/assets-raw/sprites/blocks/turrets/ripple.png and b/core/assets-raw/sprites/blocks/turrets/ripple.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/salvo.png b/core/assets-raw/sprites/blocks/turrets/salvo.png index 2f222833c1..c15a9d47cd 100644 Binary files a/core/assets-raw/sprites/blocks/turrets/salvo.png and b/core/assets-raw/sprites/blocks/turrets/salvo.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/scatter.png b/core/assets-raw/sprites/blocks/turrets/scatter.png index 5c792708e8..3a9caea04a 100644 Binary files a/core/assets-raw/sprites/blocks/turrets/scatter.png and b/core/assets-raw/sprites/blocks/turrets/scatter.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/scorch.png b/core/assets-raw/sprites/blocks/turrets/scorch.png index 3a20d8fd95..1ab0fbda81 100644 Binary files a/core/assets-raw/sprites/blocks/turrets/scorch.png and b/core/assets-raw/sprites/blocks/turrets/scorch.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/spectre.png b/core/assets-raw/sprites/blocks/turrets/spectre.png index f0e0ed7f64..71ab4e5d0e 100644 Binary files a/core/assets-raw/sprites/blocks/turrets/spectre.png and b/core/assets-raw/sprites/blocks/turrets/spectre.png differ diff --git a/core/assets-raw/sprites/blocks/turrets/swarmer.png b/core/assets-raw/sprites/blocks/turrets/swarmer.png index 1672cd8e8e..60aeb73158 100644 Binary files a/core/assets-raw/sprites/blocks/turrets/swarmer.png and b/core/assets-raw/sprites/blocks/turrets/swarmer.png differ diff --git a/core/assets-raw/sprites/blocks/units/draug-factory-top.png b/core/assets-raw/sprites/blocks/units/draug-factory-top.png new file mode 100644 index 0000000000..c20fe8d186 Binary files /dev/null and b/core/assets-raw/sprites/blocks/units/draug-factory-top.png differ diff --git a/core/assets-raw/sprites/blocks/units/draug-factory.png b/core/assets-raw/sprites/blocks/units/draug-factory.png new file mode 100644 index 0000000000..72105e12eb Binary files /dev/null and b/core/assets-raw/sprites/blocks/units/draug-factory.png differ diff --git a/core/assets-raw/sprites/blocks/units/repair-point.png b/core/assets-raw/sprites/blocks/units/repair-point.png index a0f6c69e45..5fe3b143fd 100644 Binary files a/core/assets-raw/sprites/blocks/units/repair-point.png and b/core/assets-raw/sprites/blocks/units/repair-point.png differ diff --git a/core/assets-raw/sprites/blocks/units/spirit-factory-top.png b/core/assets-raw/sprites/blocks/units/spirit-factory-top.png index c20fe8d186..a825a19d9b 100644 Binary files a/core/assets-raw/sprites/blocks/units/spirit-factory-top.png and b/core/assets-raw/sprites/blocks/units/spirit-factory-top.png differ diff --git a/core/assets-raw/sprites/ui/white.png b/core/assets-raw/sprites/effects/white.png similarity index 100% rename from core/assets-raw/sprites/ui/white.png rename to core/assets-raw/sprites/effects/white.png diff --git a/core/assets-raw/sprites/items/item-biomatter.png b/core/assets-raw/sprites/items/item-biomatter.png deleted file mode 100644 index 6dae991e87..0000000000 Binary files a/core/assets-raw/sprites/items/item-biomatter.png and /dev/null differ diff --git a/core/assets-raw/sprites/mechs/mechs/alpha-mech.png b/core/assets-raw/sprites/mechs/mechs/alpha-mech.png index 83d62471d5..623b8e7791 100644 Binary files a/core/assets-raw/sprites/mechs/mechs/alpha-mech.png and b/core/assets-raw/sprites/mechs/mechs/alpha-mech.png differ diff --git a/core/assets-raw/sprites/mechs/mechs/delta-mech.png b/core/assets-raw/sprites/mechs/mechs/delta-mech.png index e3d6e6424b..826e9e1bec 100644 Binary files a/core/assets-raw/sprites/mechs/mechs/delta-mech.png and b/core/assets-raw/sprites/mechs/mechs/delta-mech.png differ diff --git a/core/assets-raw/sprites/mechs/mechs/omega-mech.png b/core/assets-raw/sprites/mechs/mechs/omega-mech.png index 1f7c0ad626..2129eb3c08 100644 Binary files a/core/assets-raw/sprites/mechs/mechs/omega-mech.png and b/core/assets-raw/sprites/mechs/mechs/omega-mech.png differ diff --git a/core/assets-raw/sprites/mechs/mechs/tau-mech.png b/core/assets-raw/sprites/mechs/mechs/tau-mech.png index 9b6b934213..6f23a1364c 100644 Binary files a/core/assets-raw/sprites/mechs/mechs/tau-mech.png and b/core/assets-raw/sprites/mechs/mechs/tau-mech.png differ diff --git a/core/assets-raw/sprites/mechs/ships/dart-ship.png b/core/assets-raw/sprites/mechs/ships/dart-ship.png index 6ca70bcc85..e9567d8ecd 100644 Binary files a/core/assets-raw/sprites/mechs/ships/dart-ship.png and b/core/assets-raw/sprites/mechs/ships/dart-ship.png differ diff --git a/core/assets-raw/sprites/mechs/ships/glaive-ship.png b/core/assets-raw/sprites/mechs/ships/glaive-ship.png index 34aac96310..6374f07725 100644 Binary files a/core/assets-raw/sprites/mechs/ships/glaive-ship.png and b/core/assets-raw/sprites/mechs/ships/glaive-ship.png differ diff --git a/core/assets-raw/sprites/mechs/ships/javelin-ship.png b/core/assets-raw/sprites/mechs/ships/javelin-ship.png index 174d6e59cd..a9dff9a99b 100644 Binary files a/core/assets-raw/sprites/mechs/ships/javelin-ship.png and b/core/assets-raw/sprites/mechs/ships/javelin-ship.png differ diff --git a/core/assets-raw/sprites/mechs/ships/trident-ship.png b/core/assets-raw/sprites/mechs/ships/trident-ship.png index 0a4c15e5a3..e7fc0b88b1 100644 Binary files a/core/assets-raw/sprites/mechs/ships/trident-ship.png and b/core/assets-raw/sprites/mechs/ships/trident-ship.png differ diff --git a/core/assets-raw/sprites/pack_fallback.json b/core/assets-raw/sprites/pack_fallback.json deleted file mode 100644 index 853c7fc32f..0000000000 --- a/core/assets-raw/sprites/pack_fallback.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - duplicatePadding: true, - combineSubdirectories: true, - flattenPaths: true, - maxWidth: 1024, - maxHeight: 1024, - fast: true -} diff --git a/core/assets-raw/sprites/shapes/clear.png b/core/assets-raw/sprites/shapes/clear.png deleted file mode 100644 index dc8beb206c..0000000000 Binary files a/core/assets-raw/sprites/shapes/clear.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/button-disabled.9.png b/core/assets-raw/sprites/ui/button-disabled.9.png index b2e4d7eb25..a4602889e8 100644 Binary files a/core/assets-raw/sprites/ui/button-disabled.9.png and b/core/assets-raw/sprites/ui/button-disabled.9.png differ diff --git a/core/assets-raw/sprites/ui/button-down.9.png b/core/assets-raw/sprites/ui/button-down.9.png index b26d54d0a1..1cc0db6249 100644 Binary files a/core/assets-raw/sprites/ui/button-down.9.png and b/core/assets-raw/sprites/ui/button-down.9.png differ diff --git a/core/assets-raw/sprites/ui/button-edge-1.9.png b/core/assets-raw/sprites/ui/button-edge-1.9.png index b91afee83a..98f588a553 100644 Binary files a/core/assets-raw/sprites/ui/button-edge-1.9.png and b/core/assets-raw/sprites/ui/button-edge-1.9.png differ diff --git a/core/assets-raw/sprites/ui/button-edge-2.9.png b/core/assets-raw/sprites/ui/button-edge-2.9.png index 063dfa6c69..745c279f10 100644 Binary files a/core/assets-raw/sprites/ui/button-edge-2.9.png and b/core/assets-raw/sprites/ui/button-edge-2.9.png differ diff --git a/core/assets-raw/sprites/ui/button-edge-3.9.png b/core/assets-raw/sprites/ui/button-edge-3.9.png index a182e728a6..344cfc07a9 100644 Binary files a/core/assets-raw/sprites/ui/button-edge-3.9.png and b/core/assets-raw/sprites/ui/button-edge-3.9.png differ diff --git a/core/assets-raw/sprites/ui/button-edge-4.9.png b/core/assets-raw/sprites/ui/button-edge-4.9.png index c8e554c5e3..831e94fd5e 100644 Binary files a/core/assets-raw/sprites/ui/button-edge-4.9.png and b/core/assets-raw/sprites/ui/button-edge-4.9.png differ diff --git a/core/assets-raw/sprites/ui/button-over.9.png b/core/assets-raw/sprites/ui/button-over.9.png index fe5f260ce5..7effe30ffa 100644 Binary files a/core/assets-raw/sprites/ui/button-over.9.png and b/core/assets-raw/sprites/ui/button-over.9.png differ diff --git a/core/assets-raw/sprites/ui/button-red.9.png b/core/assets-raw/sprites/ui/button-red.9.png new file mode 100644 index 0000000000..621dda2ca6 Binary files /dev/null and b/core/assets-raw/sprites/ui/button-red.9.png differ diff --git a/core/assets-raw/sprites/ui/button-right-down.9.png b/core/assets-raw/sprites/ui/button-right-down.9.png index efbabad92d..c410ca7f44 100644 Binary files a/core/assets-raw/sprites/ui/button-right-down.9.png and b/core/assets-raw/sprites/ui/button-right-down.9.png differ diff --git a/core/assets-raw/sprites/ui/button-right-over.9.png b/core/assets-raw/sprites/ui/button-right-over.9.png index 1f6d0fa234..2f4a6a05bb 100644 Binary files a/core/assets-raw/sprites/ui/button-right-over.9.png and b/core/assets-raw/sprites/ui/button-right-over.9.png differ diff --git a/core/assets-raw/sprites/ui/button-right.9.png b/core/assets-raw/sprites/ui/button-right.9.png index cd3d8d52e1..dc88b76b54 100644 Binary files a/core/assets-raw/sprites/ui/button-right.9.png and b/core/assets-raw/sprites/ui/button-right.9.png differ diff --git a/core/assets-raw/sprites/ui/button-select.9.png b/core/assets-raw/sprites/ui/button-select.9.png index 73c217fc2b..a437c5b58d 100644 Binary files a/core/assets-raw/sprites/ui/button-select.9.png and b/core/assets-raw/sprites/ui/button-select.9.png differ diff --git a/core/assets-raw/sprites/ui/button.9.png b/core/assets-raw/sprites/ui/button.9.png index b88439e267..19e13554cf 100644 Binary files a/core/assets-raw/sprites/ui/button.9.png and b/core/assets-raw/sprites/ui/button.9.png differ diff --git a/core/assets-raw/sprites/ui/check-disabled.png b/core/assets-raw/sprites/ui/check-disabled.png index 68f22ed90e..53d7724049 100644 Binary files a/core/assets-raw/sprites/ui/check-disabled.png and b/core/assets-raw/sprites/ui/check-disabled.png differ diff --git a/core/assets-raw/sprites/ui/check-off.png b/core/assets-raw/sprites/ui/check-off.png index 79b86aabc1..31f800e66f 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-disabled.png b/core/assets-raw/sprites/ui/check-on-disabled.png index bd65bb214f..8eadb568e9 100644 Binary files a/core/assets-raw/sprites/ui/check-on-disabled.png and b/core/assets-raw/sprites/ui/check-on-disabled.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 716e6fffb7..5911e9ea4e 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 e4a8d11538..424e7c324f 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 5f618e5c86..39611ce341 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/content-background-locked.9.png b/core/assets-raw/sprites/ui/content-background-locked.9.png deleted file mode 100644 index 60e1941d4f..0000000000 Binary files a/core/assets-raw/sprites/ui/content-background-locked.9.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/content-background-noitems.9.png b/core/assets-raw/sprites/ui/content-background-noitems.9.png deleted file mode 100644 index f612ec98d4..0000000000 Binary files a/core/assets-raw/sprites/ui/content-background-noitems.9.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/content-background-over.9.png b/core/assets-raw/sprites/ui/content-background-over.9.png deleted file mode 100644 index 7e1a6e6c2d..0000000000 Binary files a/core/assets-raw/sprites/ui/content-background-over.9.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/content-background.9.png b/core/assets-raw/sprites/ui/content-background.9.png deleted file mode 100644 index cdd8df0abc..0000000000 Binary files a/core/assets-raw/sprites/ui/content-background.9.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/discord-banner.png b/core/assets-raw/sprites/ui/discord-banner.png index ac4d3b1ec9..d73d665602 100644 Binary files a/core/assets-raw/sprites/ui/discord-banner.png and b/core/assets-raw/sprites/ui/discord-banner.png differ diff --git a/core/assets-raw/sprites/ui/empty-sector.png b/core/assets-raw/sprites/ui/empty-sector.png deleted file mode 100644 index a0bad794cd..0000000000 Binary files a/core/assets-raw/sprites/ui/empty-sector.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/flat-down-base.9.png b/core/assets-raw/sprites/ui/flat-down-base.9.png new file mode 100644 index 0000000000..10de55d3af Binary files /dev/null and b/core/assets-raw/sprites/ui/flat-down-base.9.png differ diff --git a/core/assets-raw/sprites/ui/icons-category/icon-crafting.png b/core/assets-raw/sprites/ui/icons-category/icon-crafting.png deleted file mode 100644 index 9a5fd055e6..0000000000 Binary files a/core/assets-raw/sprites/ui/icons-category/icon-crafting.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/icons-category/icon-defense.png b/core/assets-raw/sprites/ui/icons-category/icon-defense.png deleted file mode 100644 index 150f611402..0000000000 Binary files a/core/assets-raw/sprites/ui/icons-category/icon-defense.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/icons-category/icon-distribution.png b/core/assets-raw/sprites/ui/icons-category/icon-distribution.png deleted file mode 100644 index 52a07aac9f..0000000000 Binary files a/core/assets-raw/sprites/ui/icons-category/icon-distribution.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/icons-category/icon-effect.png b/core/assets-raw/sprites/ui/icons-category/icon-effect.png deleted file mode 100644 index d0613ec868..0000000000 Binary files a/core/assets-raw/sprites/ui/icons-category/icon-effect.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/icons-category/icon-liquid.png b/core/assets-raw/sprites/ui/icons-category/icon-liquid.png deleted file mode 100644 index 050ea2ef38..0000000000 Binary files a/core/assets-raw/sprites/ui/icons-category/icon-liquid.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/icons-category/icon-power.png b/core/assets-raw/sprites/ui/icons-category/icon-power.png deleted file mode 100644 index 27d9fa885d..0000000000 Binary files a/core/assets-raw/sprites/ui/icons-category/icon-power.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/icons-category/icon-production.png b/core/assets-raw/sprites/ui/icons-category/icon-production.png deleted file mode 100644 index 8d037a43a2..0000000000 Binary files a/core/assets-raw/sprites/ui/icons-category/icon-production.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/icons-category/icon-turret.png b/core/assets-raw/sprites/ui/icons-category/icon-turret.png deleted file mode 100644 index 60cce4fa14..0000000000 Binary files a/core/assets-raw/sprites/ui/icons-category/icon-turret.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/icons-category/icon-units.png b/core/assets-raw/sprites/ui/icons-category/icon-units.png deleted file mode 100644 index d76063e640..0000000000 Binary files a/core/assets-raw/sprites/ui/icons-category/icon-units.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/icons-category/icon-upgrade.png b/core/assets-raw/sprites/ui/icons-category/icon-upgrade.png deleted file mode 100644 index af4b3f4576..0000000000 Binary files a/core/assets-raw/sprites/ui/icons-category/icon-upgrade.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/icons/controller-cursor.png b/core/assets-raw/sprites/ui/icons/controller-cursor.png deleted file mode 100644 index 061fc5b62a..0000000000 Binary files a/core/assets-raw/sprites/ui/icons/controller-cursor.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/icons/icon-admin.png b/core/assets-raw/sprites/ui/icons/icon-admin.png index 2af8d3eca6..f4101c0423 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-admin.png and b/core/assets-raw/sprites/ui/icons/icon-admin.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-areaDelete.png b/core/assets-raw/sprites/ui/icons/icon-areaDelete.png deleted file mode 100644 index e9341daca0..0000000000 Binary files a/core/assets-raw/sprites/ui/icons/icon-areaDelete.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/icons/icon-cancel-2.png b/core/assets-raw/sprites/ui/icons/icon-cancel-2.png deleted file mode 100644 index 5b14e4c468..0000000000 Binary files a/core/assets-raw/sprites/ui/icons/icon-cancel-2.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/icons/icon-changelog.png b/core/assets-raw/sprites/ui/icons/icon-changelog.png new file mode 100644 index 0000000000..e6fbf8d3c1 Binary files /dev/null and b/core/assets-raw/sprites/ui/icons/icon-changelog.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-check-2.png b/core/assets-raw/sprites/ui/icons/icon-check-2.png deleted file mode 100644 index ec0bb3cb8e..0000000000 Binary files a/core/assets-raw/sprites/ui/icons/icon-check-2.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/icons/icon-check.png b/core/assets-raw/sprites/ui/icons/icon-check.png index 1617c299c5..db96907362 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-check.png and b/core/assets-raw/sprites/ui/icons/icon-check.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-crafting.png b/core/assets-raw/sprites/ui/icons/icon-crafting.png new file mode 100644 index 0000000000..3f7022e87b Binary files /dev/null and b/core/assets-raw/sprites/ui/icons/icon-crafting.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-database-small.png b/core/assets-raw/sprites/ui/icons/icon-database-small.png deleted file mode 100644 index 059fd6f219..0000000000 Binary files a/core/assets-raw/sprites/ui/icons/icon-database-small.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/icons/icon-database.png b/core/assets-raw/sprites/ui/icons/icon-database.png index 41e4b672f2..059fd6f219 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-database.png and b/core/assets-raw/sprites/ui/icons/icon-database.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-defense.png b/core/assets-raw/sprites/ui/icons/icon-defense.png new file mode 100644 index 0000000000..2ae509685e Binary files /dev/null and b/core/assets-raw/sprites/ui/icons/icon-defense.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-dev-builds.png b/core/assets-raw/sprites/ui/icons/icon-dev-builds.png index 7edafcb7c0..27f46b6624 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-dev-builds.png and b/core/assets-raw/sprites/ui/icons/icon-dev-builds.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-distribution.png b/core/assets-raw/sprites/ui/icons/icon-distribution.png new file mode 100644 index 0000000000..3a202b38e8 Binary files /dev/null and b/core/assets-raw/sprites/ui/icons/icon-distribution.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-donate.png b/core/assets-raw/sprites/ui/icons/icon-donate.png index 5c762f79d0..cad39eb1ba 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-donate.png and b/core/assets-raw/sprites/ui/icons/icon-donate.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-editor.png b/core/assets-raw/sprites/ui/icons/icon-editor.png index bbfabe4141..6cb0a64f9f 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-editor.png and b/core/assets-raw/sprites/ui/icons/icon-editor.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-effect.png b/core/assets-raw/sprites/ui/icons/icon-effect.png new file mode 100644 index 0000000000..212034645b Binary files /dev/null and b/core/assets-raw/sprites/ui/icons/icon-effect.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-egg.png b/core/assets-raw/sprites/ui/icons/icon-egg.png deleted file mode 100644 index 11f2155605..0000000000 Binary files a/core/assets-raw/sprites/ui/icons/icon-egg.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/icons/icon-eraser.png b/core/assets-raw/sprites/ui/icons/icon-eraser.png index 00ba36cc37..fc72acc9f2 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-eraser.png and b/core/assets-raw/sprites/ui/icons/icon-eraser.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-generated.png b/core/assets-raw/sprites/ui/icons/icon-generated.png deleted file mode 100644 index f8630b8242..0000000000 Binary files a/core/assets-raw/sprites/ui/icons/icon-generated.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/icons/icon-github.png b/core/assets-raw/sprites/ui/icons/icon-github.png index dafadb05fb..0de41be50d 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-github.png and b/core/assets-raw/sprites/ui/icons/icon-github.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-google-play.png b/core/assets-raw/sprites/ui/icons/icon-google-play.png index b42f628d31..8464c51159 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-google-play.png and b/core/assets-raw/sprites/ui/icons/icon-google-play.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-hold.png b/core/assets-raw/sprites/ui/icons/icon-hold.png deleted file mode 100644 index fc40846ebe..0000000000 Binary files a/core/assets-raw/sprites/ui/icons/icon-hold.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/icons/icon-holdDelete.png b/core/assets-raw/sprites/ui/icons/icon-holdDelete.png deleted file mode 100644 index 56c2aff291..0000000000 Binary files a/core/assets-raw/sprites/ui/icons/icon-holdDelete.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/icons/icon-info.png b/core/assets-raw/sprites/ui/icons/icon-info.png index e3461da338..7e2bb40037 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-info.png and b/core/assets-raw/sprites/ui/icons/icon-info.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-itch.io.png b/core/assets-raw/sprites/ui/icons/icon-itch.io.png index 4cf4b3cfe6..b5bca0e50a 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-itch.io.png and b/core/assets-raw/sprites/ui/icons/icon-itch.io.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-items-none.png b/core/assets-raw/sprites/ui/icons/icon-items-none.png deleted file mode 100644 index b90595d9ee..0000000000 Binary files a/core/assets-raw/sprites/ui/icons/icon-items-none.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/icons/icon-liquid-small.png b/core/assets-raw/sprites/ui/icons/icon-liquid-consume.png similarity index 100% rename from core/assets-raw/sprites/ui/icons/icon-liquid-small.png rename to core/assets-raw/sprites/ui/icons/icon-liquid-consume.png diff --git a/core/assets-raw/sprites/ui/icons/icon-liquid.png b/core/assets-raw/sprites/ui/icons/icon-liquid.png new file mode 100644 index 0000000000..1306834469 Binary files /dev/null and b/core/assets-raw/sprites/ui/icons/icon-liquid.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-loading.png b/core/assets-raw/sprites/ui/icons/icon-loading.png index b857848f9a..0fd2d5265d 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-loading.png and b/core/assets-raw/sprites/ui/icons/icon-loading.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-locked.png b/core/assets-raw/sprites/ui/icons/icon-locked.png index c76abf6346..cdf11fe658 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-locked.png and b/core/assets-raw/sprites/ui/icons/icon-locked.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-logic.png b/core/assets-raw/sprites/ui/icons/icon-logic.png deleted file mode 100644 index 8ad3313701..0000000000 Binary files a/core/assets-raw/sprites/ui/icons/icon-logic.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/icons/icon-map.png b/core/assets-raw/sprites/ui/icons/icon-map.png index 8891e80a71..92ff76d74f 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-map.png and b/core/assets-raw/sprites/ui/icons/icon-map.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-mission-background.png b/core/assets-raw/sprites/ui/icons/icon-mission-background.png deleted file mode 100644 index 3dc92b6a77..0000000000 Binary files a/core/assets-raw/sprites/ui/icons/icon-mission-background.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/icons/icon-mission-battle.png b/core/assets-raw/sprites/ui/icons/icon-mission-battle.png deleted file mode 100644 index 8c044dcf45..0000000000 Binary files a/core/assets-raw/sprites/ui/icons/icon-mission-battle.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/icons/icon-mission-defense.png b/core/assets-raw/sprites/ui/icons/icon-mission-defense.png deleted file mode 100644 index dc503fa345..0000000000 Binary files a/core/assets-raw/sprites/ui/icons/icon-mission-defense.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/icons/icon-mission-done.png b/core/assets-raw/sprites/ui/icons/icon-mission-done.png deleted file mode 100644 index 088f735f17..0000000000 Binary files a/core/assets-raw/sprites/ui/icons/icon-mission-done.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/icons/icon-mode-attack.png b/core/assets-raw/sprites/ui/icons/icon-mode-attack.png new file mode 100644 index 0000000000..c6aac86259 Binary files /dev/null and b/core/assets-raw/sprites/ui/icons/icon-mode-attack.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-mode-pvp.png b/core/assets-raw/sprites/ui/icons/icon-mode-pvp.png new file mode 100644 index 0000000000..a98bb81e01 Binary files /dev/null and b/core/assets-raw/sprites/ui/icons/icon-mode-pvp.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-mode-survival.png b/core/assets-raw/sprites/ui/icons/icon-mode-survival.png new file mode 100644 index 0000000000..c88da7b3b6 Binary files /dev/null and b/core/assets-raw/sprites/ui/icons/icon-mode-survival.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-pencil-small.png b/core/assets-raw/sprites/ui/icons/icon-pencil-small.png deleted file mode 100644 index 71a25add80..0000000000 Binary files a/core/assets-raw/sprites/ui/icons/icon-pencil-small.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/icons/icon-pencil.png b/core/assets-raw/sprites/ui/icons/icon-pencil.png index 448e3ef02b..053a283d08 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-pencil.png and b/core/assets-raw/sprites/ui/icons/icon-pencil.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-pick.png b/core/assets-raw/sprites/ui/icons/icon-pick.png index e833f22561..dfd7743030 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-pick.png and b/core/assets-raw/sprites/ui/icons/icon-pick.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-power-requirement.png b/core/assets-raw/sprites/ui/icons/icon-power-requirement.png deleted file mode 100644 index a6deaa19bc..0000000000 Binary files a/core/assets-raw/sprites/ui/icons/icon-power-requirement.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/icons/icon-power-small.png b/core/assets-raw/sprites/ui/icons/icon-power-small.png deleted file mode 100644 index 666058d5c7..0000000000 Binary files a/core/assets-raw/sprites/ui/icons/icon-power-small.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/icons/icon-power.png b/core/assets-raw/sprites/ui/icons/icon-power.png new file mode 100644 index 0000000000..57fbb2f2bd Binary files /dev/null and b/core/assets-raw/sprites/ui/icons/icon-power.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-production.png b/core/assets-raw/sprites/ui/icons/icon-production.png new file mode 100644 index 0000000000..fe6c3523c0 Binary files /dev/null and b/core/assets-raw/sprites/ui/icons/icon-production.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-redo.png b/core/assets-raw/sprites/ui/icons/icon-redo.png index b563616f62..4c53eb56ef 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-redo.png and b/core/assets-raw/sprites/ui/icons/icon-redo.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-refresh.png b/core/assets-raw/sprites/ui/icons/icon-refresh.png index ef69be3960..cd1050f017 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-refresh.png and b/core/assets-raw/sprites/ui/icons/icon-refresh.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-terrain.png b/core/assets-raw/sprites/ui/icons/icon-terrain.png index 4f6326e012..cc9c57380e 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-terrain.png and b/core/assets-raw/sprites/ui/icons/icon-terrain.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-tools.png b/core/assets-raw/sprites/ui/icons/icon-tools.png index 0c6a1016a1..2ece1ae8f4 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-tools.png and b/core/assets-raw/sprites/ui/icons/icon-tools.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-touch.png b/core/assets-raw/sprites/ui/icons/icon-touch.png deleted file mode 100644 index 54f86930dd..0000000000 Binary files a/core/assets-raw/sprites/ui/icons/icon-touch.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/icons/icon-touchDelete.png b/core/assets-raw/sprites/ui/icons/icon-touchDelete.png deleted file mode 100644 index 484ecf1bac..0000000000 Binary files a/core/assets-raw/sprites/ui/icons/icon-touchDelete.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/icons/icon-tree-locked.png b/core/assets-raw/sprites/ui/icons/icon-tree-locked.png deleted file mode 100644 index 5c9678c8a9..0000000000 Binary files a/core/assets-raw/sprites/ui/icons/icon-tree-locked.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/icons/icon-turret.png b/core/assets-raw/sprites/ui/icons/icon-turret.png new file mode 100644 index 0000000000..32fd01b464 Binary files /dev/null and b/core/assets-raw/sprites/ui/icons/icon-turret.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-undo.png b/core/assets-raw/sprites/ui/icons/icon-undo.png index 98f74d8de9..cf5dd4c154 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-undo.png and b/core/assets-raw/sprites/ui/icons/icon-undo.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-units.png b/core/assets-raw/sprites/ui/icons/icon-units.png new file mode 100644 index 0000000000..1ee9cd9f55 Binary files /dev/null and b/core/assets-raw/sprites/ui/icons/icon-units.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-unlocked.png b/core/assets-raw/sprites/ui/icons/icon-unlocked.png deleted file mode 100644 index 9eedca0a66..0000000000 Binary files a/core/assets-raw/sprites/ui/icons/icon-unlocked.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/icons/icon-upgrade.png b/core/assets-raw/sprites/ui/icons/icon-upgrade.png new file mode 100644 index 0000000000..80e416aebe Binary files /dev/null and b/core/assets-raw/sprites/ui/icons/icon-upgrade.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-wiki.png b/core/assets-raw/sprites/ui/icons/icon-wiki.png index b97008c439..a4395e4ed5 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-wiki.png and b/core/assets-raw/sprites/ui/icons/icon-wiki.png differ diff --git a/core/assets-raw/sprites/ui/icons/icon-zone-locked.png b/core/assets-raw/sprites/ui/icons/icon-zone-locked.png deleted file mode 100644 index b0b184918c..0000000000 Binary files a/core/assets-raw/sprites/ui/icons/icon-zone-locked.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/icons/icon-zone.png b/core/assets-raw/sprites/ui/icons/icon-zone.png deleted file mode 100644 index 2496b1bc79..0000000000 Binary files a/core/assets-raw/sprites/ui/icons/icon-zone.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/icons/icon-zoom-small.png b/core/assets-raw/sprites/ui/icons/icon-zoom-small.png deleted file mode 100644 index af547625b0..0000000000 Binary files a/core/assets-raw/sprites/ui/icons/icon-zoom-small.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/icons/icon-zoom.png b/core/assets-raw/sprites/ui/icons/icon-zoom.png index fb5948a596..02736c1a4b 100644 Binary files a/core/assets-raw/sprites/ui/icons/icon-zoom.png and b/core/assets-raw/sprites/ui/icons/icon-zoom.png differ diff --git a/core/assets-raw/sprites/ui/info-banner.png b/core/assets-raw/sprites/ui/info-banner.png index 3568944de5..0ee4c4ad83 100644 Binary files a/core/assets-raw/sprites/ui/info-banner.png and b/core/assets-raw/sprites/ui/info-banner.png differ diff --git a/core/assets-raw/sprites/ui/inventory.9.png b/core/assets-raw/sprites/ui/inventory.9.png index 53a5632587..0bbff5a0fe 100644 Binary files a/core/assets-raw/sprites/ui/inventory.9.png and b/core/assets-raw/sprites/ui/inventory.9.png differ diff --git a/core/assets-raw/sprites/ui/logotext.png b/core/assets-raw/sprites/ui/logotext.png deleted file mode 100644 index 64976a6c47..0000000000 Binary files a/core/assets-raw/sprites/ui/logotext.png and /dev/null differ diff --git a/core/assets-raw/sprites/blocks/environment/pack_fallback.json b/core/assets-raw/sprites/ui/pack.json similarity index 72% rename from core/assets-raw/sprites/blocks/environment/pack_fallback.json rename to core/assets-raw/sprites/ui/pack.json index 853c7fc32f..2612f17acc 100644 --- a/core/assets-raw/sprites/blocks/environment/pack_fallback.json +++ b/core/assets-raw/sprites/ui/pack.json @@ -2,7 +2,7 @@ duplicatePadding: true, combineSubdirectories: true, flattenPaths: true, - maxWidth: 1024, - maxHeight: 1024, + maxWidth: 2048, + maxHeight: 2048, fast: true } diff --git a/core/assets-raw/sprites/ui/pane-2.9.png b/core/assets-raw/sprites/ui/pane-2.9.png index e2fe497574..417dcd02fd 100644 Binary files a/core/assets-raw/sprites/ui/pane-2.9.png and b/core/assets-raw/sprites/ui/pane-2.9.png differ diff --git a/core/assets-raw/sprites/ui/pane.9.png b/core/assets-raw/sprites/ui/pane.9.png index a21c4607aa..885a5c45f3 100644 Binary files a/core/assets-raw/sprites/ui/pane.9.png and b/core/assets-raw/sprites/ui/pane.9.png differ diff --git a/core/assets-raw/sprites/ui/scroll-knob-horizontal-black.9.png b/core/assets-raw/sprites/ui/scroll-knob-horizontal-black.9.png index 7f5dd4137f..7a3bac9b10 100644 Binary files a/core/assets-raw/sprites/ui/scroll-knob-horizontal-black.9.png and b/core/assets-raw/sprites/ui/scroll-knob-horizontal-black.9.png differ diff --git a/core/assets-raw/sprites/ui/scroll-knob-vertical-black.9.png b/core/assets-raw/sprites/ui/scroll-knob-vertical-black.9.png index 1b5c9d39d8..17d9dcf726 100644 Binary files a/core/assets-raw/sprites/ui/scroll-knob-vertical-black.9.png and b/core/assets-raw/sprites/ui/scroll-knob-vertical-black.9.png differ diff --git a/core/assets-raw/sprites/ui/sector-select.png b/core/assets-raw/sprites/ui/sector-select.png deleted file mode 100644 index 79987b507f..0000000000 Binary files a/core/assets-raw/sprites/ui/sector-select.png and /dev/null differ diff --git a/core/assets-raw/sprites/ui/slider-knob-down.png b/core/assets-raw/sprites/ui/slider-knob-down.png index 2822be93af..32fd414a91 100644 Binary files a/core/assets-raw/sprites/ui/slider-knob-down.png and b/core/assets-raw/sprites/ui/slider-knob-down.png differ diff --git a/core/assets-raw/sprites/ui/slider-knob-over.png b/core/assets-raw/sprites/ui/slider-knob-over.png index 2822be93af..d0dde09ecc 100644 Binary files a/core/assets-raw/sprites/ui/slider-knob-over.png and b/core/assets-raw/sprites/ui/slider-knob-over.png differ diff --git a/core/assets-raw/sprites/ui/slider-knob.png b/core/assets-raw/sprites/ui/slider-knob.png index 4d98387c78..1c40347ea0 100644 Binary files a/core/assets-raw/sprites/ui/slider-knob.png and b/core/assets-raw/sprites/ui/slider-knob.png differ diff --git a/core/assets-raw/sprites/ui/slider.png b/core/assets-raw/sprites/ui/slider.png index 278674e9a0..71b354ccc9 100644 Binary files a/core/assets-raw/sprites/ui/slider.png and b/core/assets-raw/sprites/ui/slider.png differ diff --git a/core/assets-raw/sprites/ui/underline-2.9.png b/core/assets-raw/sprites/ui/underline-2.9.png index f703111db2..24da68912a 100644 Binary files a/core/assets-raw/sprites/ui/underline-2.9.png and b/core/assets-raw/sprites/ui/underline-2.9.png differ diff --git a/core/assets-raw/sprites/ui/underline-disabled.9.png b/core/assets-raw/sprites/ui/underline-disabled.9.png index 753a3e9c24..778b428500 100644 Binary files a/core/assets-raw/sprites/ui/underline-disabled.9.png and b/core/assets-raw/sprites/ui/underline-disabled.9.png differ diff --git a/core/assets-raw/sprites/ui/underline-red.9.png b/core/assets-raw/sprites/ui/underline-red.9.png index 5a6bc60651..1237745208 100644 Binary files a/core/assets-raw/sprites/ui/underline-red.9.png and b/core/assets-raw/sprites/ui/underline-red.9.png differ diff --git a/core/assets-raw/sprites/ui/underline.9.png b/core/assets-raw/sprites/ui/underline.9.png index e42d29c78f..516f6f82cc 100644 Binary files a/core/assets-raw/sprites/ui/underline.9.png and b/core/assets-raw/sprites/ui/underline.9.png differ diff --git a/core/assets-raw/sprites/ui/whiteui.png b/core/assets-raw/sprites/ui/whiteui.png new file mode 100644 index 0000000000..ba9bf827c1 Binary files /dev/null and b/core/assets-raw/sprites/ui/whiteui.png differ diff --git a/core/assets-raw/sprites/units/draug.png b/core/assets-raw/sprites/units/draug.png new file mode 100644 index 0000000000..e8bd233336 Binary files /dev/null and b/core/assets-raw/sprites/units/draug.png differ diff --git a/core/assets-raw/sprites/weapons/blaster-equip.png b/core/assets-raw/sprites/weapons/blaster-equip.png index e8d35d7c9e..b5679122a5 100644 Binary files a/core/assets-raw/sprites/weapons/blaster-equip.png and b/core/assets-raw/sprites/weapons/blaster-equip.png differ diff --git a/core/assets-raw/sprites/weapons/flakgun-equip.png b/core/assets-raw/sprites/weapons/flakgun-equip.png index c264823bb3..931b33dd1d 100644 Binary files a/core/assets-raw/sprites/weapons/flakgun-equip.png and b/core/assets-raw/sprites/weapons/flakgun-equip.png differ diff --git a/core/assets-raw/sprites/weapons/heal-blaster-equip.png b/core/assets-raw/sprites/weapons/heal-blaster-equip.png index 4499364ab9..52f579ce68 100644 Binary files a/core/assets-raw/sprites/weapons/heal-blaster-equip.png and b/core/assets-raw/sprites/weapons/heal-blaster-equip.png differ diff --git a/core/assets-raw/sprites/weapons/shockgun-equip.png b/core/assets-raw/sprites/weapons/shockgun-equip.png index 5710b7c655..c53587d7ee 100644 Binary files a/core/assets-raw/sprites/weapons/shockgun-equip.png and b/core/assets-raw/sprites/weapons/shockgun-equip.png differ diff --git a/core/assets-raw/sprites/weapons/swarmer-equip.png b/core/assets-raw/sprites/weapons/swarmer-equip.png index 68de627f44..6d818dcaac 100644 Binary files a/core/assets-raw/sprites/weapons/swarmer-equip.png and b/core/assets-raw/sprites/weapons/swarmer-equip.png differ diff --git a/core/assets/bloomshaders/alpha_bloom.fragment.glsl b/core/assets/bloomshaders/alpha_bloom.fragment.glsl new file mode 100644 index 0000000000..00444c1dca --- /dev/null +++ b/core/assets/bloomshaders/alpha_bloom.fragment.glsl @@ -0,0 +1,23 @@ +#ifdef GL_ES +#define LOWP lowp +#define MED mediump +precision lowp float; +#else +#define LOWP +#define MED +#endif +uniform sampler2D u_texture0; +uniform sampler2D u_texture1; +uniform float BloomIntensity; +uniform float OriginalIntensity; + +varying MED vec2 v_texCoords; + +void main() +{ + + vec4 original = texture2D(u_texture0, v_texCoords) * OriginalIntensity; + vec4 bloom = texture2D(u_texture1, v_texCoords) * BloomIntensity; + original = original * (vec4(1.0) - bloom); + gl_FragColor = original + bloom; +} \ No newline at end of file diff --git a/core/assets/bloomshaders/alpha_gaussian.fragment.glsl b/core/assets/bloomshaders/alpha_gaussian.fragment.glsl new file mode 100644 index 0000000000..e060efc278 --- /dev/null +++ b/core/assets/bloomshaders/alpha_gaussian.fragment.glsl @@ -0,0 +1,26 @@ +#ifdef GL_ES +#define LOWP lowp +#define MED mediump +precision lowp float; +#else +#define LOWP +#define MED +#endif + +uniform sampler2D u_texture; +varying MED vec2 v_texCoords0; +varying MED vec2 v_texCoords1; +varying MED vec2 v_texCoords2; +varying MED vec2 v_texCoords3; +varying MED vec2 v_texCoords4; +const float center = 0.2270270270; +const float close = 0.3162162162; +const float far = 0.0702702703; +void main() +{ + gl_FragColor = far * texture2D(u_texture, v_texCoords0) + + close * texture2D(u_texture, v_texCoords1) + + center * texture2D(u_texture, v_texCoords2) + + close * texture2D(u_texture, v_texCoords3) + + far * texture2D(u_texture, v_texCoords4); +} diff --git a/core/assets/bloomshaders/alpha_threshold.fragment.glsl b/core/assets/bloomshaders/alpha_threshold.fragment.glsl new file mode 100644 index 0000000000..d85c0b1170 --- /dev/null +++ b/core/assets/bloomshaders/alpha_threshold.fragment.glsl @@ -0,0 +1,21 @@ +#ifdef GL_ES +#define LOWP lowp +#define MED mediump +precision lowp float; +#else +#define LOWP +#define MED +#endif +uniform sampler2D u_texture0; +uniform vec2 threshold; +varying MED vec2 v_texCoords; +void main() +{ + vec4 color = texture2D(u_texture0, v_texCoords); + if(color.r + color.g + color.b > 0.5 * 3.0){ + gl_FragColor = color; + }else{ + gl_FragColor = vec4(0.0); + } + //gl_FragColor = (texture2D(u_texture0, v_texCoords) - vec4(threshold.r)) * threshold.g; +} \ No newline at end of file diff --git a/core/assets/bloomshaders/bloom.fragment.glsl b/core/assets/bloomshaders/bloom.fragment.glsl new file mode 100644 index 0000000000..93bbfe3737 --- /dev/null +++ b/core/assets/bloomshaders/bloom.fragment.glsl @@ -0,0 +1,23 @@ +#ifdef GL_ES +#define LOWP lowp +#define MED mediump +precision lowp float; +#else +#define LOWP +#define MED +#endif +uniform sampler2D u_texture0; +uniform sampler2D u_texture1; +uniform float BloomIntensity; +uniform float OriginalIntensity; + +varying MED vec2 v_texCoords; + +void main() +{ + + vec3 original = texture2D(u_texture0, v_texCoords).rgb; + vec3 bloom = texture2D(u_texture1, v_texCoords).rgb * BloomIntensity; + original = OriginalIntensity * (original - original * bloom); + gl_FragColor.rgb = original + bloom; +} \ No newline at end of file diff --git a/core/assets/bloomshaders/blurspace.vertex.glsl b/core/assets/bloomshaders/blurspace.vertex.glsl new file mode 100644 index 0000000000..1d7135d9ab --- /dev/null +++ b/core/assets/bloomshaders/blurspace.vertex.glsl @@ -0,0 +1,31 @@ +#ifdef GL_ES +#define MED mediump +#else +#define MED +#endif + +attribute vec4 a_position; +attribute vec2 a_texCoord0; +uniform vec2 dir; +uniform vec2 size; +varying MED vec2 v_texCoords0; +varying MED vec2 v_texCoords1; +varying MED vec2 v_texCoords2; +varying MED vec2 v_texCoords3; +varying MED vec2 v_texCoords4; +const vec2 futher = vec2(3.2307692308, 3.2307692308); +const vec2 closer = vec2(1.3846153846, 1.3846153846); +void main() +{ + vec2 sizeAndDir = dir / size; + vec2 f = futher*sizeAndDir; + vec2 c = closer*sizeAndDir; + + v_texCoords0 = a_texCoord0 - f; + v_texCoords1 = a_texCoord0 - c; + v_texCoords2 = a_texCoord0; + v_texCoords3 = a_texCoord0 + c; + v_texCoords4 = a_texCoord0 + f; + + gl_Position = a_position; +} \ No newline at end of file diff --git a/core/assets/bloomshaders/gaussian.fragment.glsl b/core/assets/bloomshaders/gaussian.fragment.glsl new file mode 100644 index 0000000000..5373349f85 --- /dev/null +++ b/core/assets/bloomshaders/gaussian.fragment.glsl @@ -0,0 +1,26 @@ +#ifdef GL_ES +#define LOWP lowp +#define MED mediump +precision lowp float; +#else +#define LOWP +#define MED +#endif + +uniform sampler2D u_texture; +varying MED vec2 v_texCoords0; +varying MED vec2 v_texCoords1; +varying MED vec2 v_texCoords2; +varying MED vec2 v_texCoords3; +varying MED vec2 v_texCoords4; +const float center = 0.2270270270; +const float close = 0.3162162162; +const float far = 0.0702702703; +void main() +{ + gl_FragColor.rgb = far * texture2D(u_texture, v_texCoords0).rgb + + close * texture2D(u_texture, v_texCoords1).rgb + + center * texture2D(u_texture, v_texCoords2).rgb + + close * texture2D(u_texture, v_texCoords3).rgb + + far * texture2D(u_texture, v_texCoords4).rgb; +} diff --git a/core/assets/bloomshaders/maskedtreshold.fragment.glsl b/core/assets/bloomshaders/maskedtreshold.fragment.glsl new file mode 100644 index 0000000000..a65064e380 --- /dev/null +++ b/core/assets/bloomshaders/maskedtreshold.fragment.glsl @@ -0,0 +1,17 @@ +#ifdef GL_ES +#define LOWP lowp +#define MED mediump +precision lowp float; +#else +#define LOWP +#define MED +#endif +uniform sampler2D u_texture0; +uniform vec2 threshold; +varying MED vec2 v_texCoords; +void main() +{ + vec4 tex = texture2D(u_texture0, v_texCoords); + vec3 colors = (tex.rgb - threshold.r) * threshold.g * tex.a; + gl_FragColor = vec4(colors, tex.a); +} \ No newline at end of file diff --git a/core/assets/bloomshaders/screenspace.vertex.glsl b/core/assets/bloomshaders/screenspace.vertex.glsl new file mode 100644 index 0000000000..8e521c9a75 --- /dev/null +++ b/core/assets/bloomshaders/screenspace.vertex.glsl @@ -0,0 +1,13 @@ +#ifdef GL_ES +#define MED mediump +#else +#define MED +#endif +attribute vec4 a_position; +attribute vec2 a_texCoord0; +varying MED vec2 v_texCoords; +void main() +{ + v_texCoords = a_texCoord0; + gl_Position = a_position; +} \ No newline at end of file diff --git a/core/assets/bloomshaders/threshold.fragment.glsl b/core/assets/bloomshaders/threshold.fragment.glsl new file mode 100644 index 0000000000..52de3f18ed --- /dev/null +++ b/core/assets/bloomshaders/threshold.fragment.glsl @@ -0,0 +1,15 @@ +#ifdef GL_ES +#define LOWP lowp +#define MED mediump +precision lowp float; +#else +#define LOWP +#define MED +#endif +uniform sampler2D u_texture0; +uniform vec2 threshold; +varying MED vec2 v_texCoords; +void main() +{ + gl_FragColor.rgb = (texture2D(u_texture0, v_texCoords).rgb - vec3(threshold.x)) * threshold.y; +} \ No newline at end of file diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 74c88600fc..9590daeba9 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -4,9 +4,10 @@ contributors = Translators and Contributors discord = Join the Mindustry Discord! link.discord.description = The official Mindustry Discord chatroom link.github.description = Game source code +link.changelog.description = List of update changes link.dev-builds.description = Unstable development builds link.trello.description = Official Trello board for planned features -link.itch.io.description = itch.io page with PC downloads and web version +link.itch.io.description = itch.io page with PC downloads link.google-play.description = Google Play store listing link.wiki.description = Official Mindustry wiki linkfail = Failed to open link!\nThe URL has been copied to your clipboard. @@ -35,7 +36,6 @@ level.mode = Gamemode: showagain = Don't show again next session coreattack = < Core is under attack! > nearpoint = [[ [scarlet]LEAVE DROP POINT IMMEDIATELY[] ]\nannihilation imminent -outofbounds = [[ OUT OF BOUNDS ]\n[]self-destruct in {0} database = Core Database savegame = Save Game loadgame = Load Game @@ -49,7 +49,7 @@ close = Close quit = Quit maps = Maps continue = Continue -maps.none = [LIGHT_GRAY]No maps found! +maps.none = [lightgray]No maps found! about.button = About name = Name: noname = Pick a[accent] player name[] first. @@ -57,9 +57,9 @@ filename = File Name: unlocked = New content unlocked! completed = [accent]Completed techtree = Tech Tree -research.list = [LIGHT_GRAY]Research: +research.list = [lightgray]Research: research = Research -researched = [LIGHT_GRAY]{0} researched. +researched = [lightgray]{0} researched. players = {0} players online players.single = {0} player online server.closing = [accent]Closing server... @@ -74,8 +74,8 @@ server.kicked.nameEmpty = Your chosen name is invalid. server.kicked.idInUse = You are already on this server! Connecting with two accounts is not permitted. server.kicked.customClient = This server does not support custom builds. Download an official version. server.kicked.gameover = Game over! -host.info = The [accent]host[] button hosts a server on port [scarlet]6567[]. \nAnybody on the same [LIGHT_GRAY]wifi or local network[] should be able to see your server in their server list.\n\nIf you want people to be able to connect from anywhere by IP, [accent]port forwarding[] is required.\n\n[LIGHT_GRAY]Note: If someone is experiencing trouble connecting to your LAN game, make sure you have allowed Mindustry access to your local network in your firewall settings. -join.info = Here, you can enter a [accent]server IP[] to connect to, or discover [accent]local network[] servers to connect to.\nBoth LAN and WAN multiplayer is supported.\n\n[LIGHT_GRAY]Note: There is no automatic global server list; if you want to connect to someone by IP, you would need to ask the host for their IP. +host.info = The [accent]host[] button hosts a server on port [scarlet]6567[]. \nAnybody on the same [lightgray]wifi or local network[] should be able to see your server in their server list.\n\nIf you want people to be able to connect from anywhere by IP, [accent]port forwarding[] is required.\n\n[lightgray]Note: If someone is experiencing trouble connecting to your LAN game, make sure you have allowed Mindustry access to your local network in your firewall settings. +join.info = Here, you can enter a [accent]server IP[] to connect to, or discover [accent]local network[] servers to connect to.\nBoth LAN and WAN multiplayer is supported.\n\n[lightgray]Note: There is no automatic global server list; if you want to connect to someone by IP, you would need to ask the host for their IP. hostserver = Host Game hostserver.mobile = Host\nGame host = Host @@ -98,11 +98,10 @@ server.admins = Admins server.admins.none = No admins found! server.add = Add Server server.delete = Are you sure you want to delete this server? -server.hostname = Host: {0} server.edit = Edit Server server.outdated = [crimson]Outdated Server![] server.outdated.client = [crimson]Outdated Client![] -server.version = [lightgray]Version: {0} {1} +server.version = [gray]v{0} {1} server.custombuild = [yellow]Custom Build confirmban = Are you sure you want to ban this player? confirmkick = Are you sure you want to kick this player? @@ -119,7 +118,7 @@ server.port = Port: server.addressinuse = Address already in use! server.invalidport = Invalid port number! server.error = [crimson]Error hosting server: [accent]{0} -save.old = This save is for an older version of the game, and can no longer be used.\n\n[LIGHT_GRAY]Save backwards compatibility will be implemented in the full 4.0 release. +save.old = This save is for an older version of the game, and can no longer be used.\n\n[lightgray]Save backwards compatibility will be implemented in the full 4.0 release. save.new = New Save save.overwrite = Are you sure you want to overwrite\nthis save slot? overwrite = Overwrite @@ -153,28 +152,21 @@ confirm = Confirm delete = Delete ok = OK open = Open -customize = Customize +customize = Customize Rules cancel = Cancel openlink = Open Link copylink = Copy Link back = Back quit.confirm = Are you sure you want to quit? -changelog.title = Changelog -changelog.loading = Getting changelog... -changelog.error.android = [accent]Note that the changelog sometimes does not work on Android 4.4 and below!\nThis is due to an internal Android bug. -changelog.error.ios = [accent]The changelog is currently not supported in iOS. -changelog.error = [scarlet]Error getting changelog!\nCheck your internet connection. -changelog.current = [yellow][[Current version] -changelog.latest = [accent][[Latest version] loading = [accent]Loading... saving = [accent]Saving... wave = [accent]Wave {0} -wave.waiting = [LIGHT_GRAY]Wave in {0} -wave.waveInProgress = [LIGHT_GRAY]Wave in progress -waiting = [LIGHT_GRAY]Waiting... +wave.waiting = [lightgray]Wave in {0} +wave.waveInProgress = [lightgray]Wave in progress +waiting = [lightgray]Waiting... waiting.players = Waiting for players... -wave.enemies = [LIGHT_GRAY]{0} Enemies Remaining -wave.enemy = [LIGHT_GRAY]{0} Enemy Remaining +wave.enemies = [lightgray]{0} Enemies Remaining +wave.enemy = [lightgray]{0} Enemy Remaining loadimage = Load Image saveimage = Save Image unknown = Unknown @@ -195,7 +187,9 @@ editor.author = Author: editor.description = Description: editor.waves = Waves: editor.rules = Rules: +editor.generation = Generation: editor.ingame = Edit In-Game +editor.newmap = New Map waves.title = Waves waves.remove = Remove waves.never = @@ -210,13 +204,13 @@ waves.copy = Copy to Clipboard waves.load = Load from Clipboard waves.invalid = Invalid waves in clipboard. waves.copied = Waves copied. -editor.default = [LIGHT_GRAY] +waves.none = No enemies defined.\nNote that empty wave layouts will automatically be replaced with the default layout. +editor.default = [lightgray] edit = Edit... editor.name = Name: editor.spawn = Spawn Unit editor.removeunit = Remove Unit editor.teams = Teams -editor.elevation = Elevation editor.errorload = Error loading file:\n[accent]{0} editor.errorsave = Error saving file:\n[accent]{0} editor.errorimage = That's an image, not a map. Don't go around changing extensions expecting it to work.\n\nIf you want to import a legacy map, use the 'import legacy map' button in the editor. @@ -254,11 +248,33 @@ 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. + +toolmode.replace = Replace +toolmode.replace.description = Draws only on solid blocks. +toolmode.replaceall = Replace All +toolmode.replaceall.description = Replace all blocks in map. +toolmode.orthogonal = Orthogonal +toolmode.orthogonal.description = Draws only orthogonal lines. +toolmode.square = Square +toolmode.square.description = Square brush. +toolmode.eraseores = Erase Ores +toolmode.eraseores.description = Erase only ores. +toolmode.fillteams = Fill Teams +toolmode.fillteams.description = Fill teams instead of blocks. +toolmode.drawteams = Draw Teams +toolmode.drawteams.description = Draw teams instead of blocks. + +filters.empty = [lightgray]No filters! Add one with the button below. filter.distort = Distort filter.noise = Noise +filter.median = Median +filter.blend = Blend +filter.defaultores = Default Ores filter.ore = Ore filter.rivernoise = River Noise +filter.mirror = Mirror +filter.clear = Clear +filter.option.ignore = Ignore filter.scatter = Scatter filter.terrain = Terrain filter.option.scale = Scale @@ -268,18 +284,22 @@ filter.option.threshold = Threshold filter.option.circle-scale = Circle Scale filter.option.octaves = Octaves filter.option.falloff = Falloff +filter.option.angle = Angle filter.option.block = Block filter.option.floor = Floor +filter.option.flooronto = Target Floor filter.option.wall = Wall filter.option.ore = Ore filter.option.floor2 = Secondary Floor filter.option.threshold2 = Secondary Threshold filter.option.radius = Radius filter.option.percentile = Percentile + width = Width: height = Height: menu = Menu play = Play +campaign = Campaign load = Load save = Save fps = FPS: {0} @@ -295,26 +315,29 @@ donate = Donate abandon = Abandon abandon.text = This zone and all its resources will be lost to the enemy. locked = Locked -complete = [LIGHT_GRAY]Reach: +complete = [lightgray]Reach: zone.requirement = Wave {0} in zone {1} -resume = Resume Zone:\n[LIGHT_GRAY]{0} -bestwave = [LIGHT_GRAY]Best Wave: {0} +resume = Resume Zone:\n[lightgray]{0} +bestwave = [lightgray]Best Wave: {0} launch = < LAUNCH > launch.title = Launch Successful -launch.next = [LIGHT_GRAY]next opportunity at wave {0} +launch.next = [lightgray]next opportunity at wave {0} launch.unable = [scarlet]Unable to LAUNCH.[] {0} Enemies. launch.confirm = This will launch all resources in your core.\nYou will not be able to return to this base. uncover = Uncover configure = Configure Loadout -configure.locked = [LIGHT_GRAY]Unlock configuring loadout: Wave {0}. -zone.unlocked = [LIGHT_GRAY]{0} unlocked. +configure.locked = [lightgray]Unlock configuring loadout: Wave {0}. +zone.unlocked = [lightgray]{0} unlocked. zone.requirement.complete = Wave {0} reached:\n{1} zone requirements met. zone.config.complete = Wave {0} reached:\nLoadout config unlocked. -zone.resources = Resources Detected: +zone.resources = [lightgray]Resources Detected: +zone.objective = [lightgray]Objective: [accent]{0} +zone.objective.survival = Survive +zone.objective.attack = Destroy Enemy Core add = Add... boss.health = Boss Health -connectfail = [crimson]Failed to connect to server:\n\n[accent]{0} +connectfail = [crimson]Connection error:\n\n[accent]{0} error.unreachable = Server unreachable.\nIs the address spelled correctly? error.invalidaddress = Invalid address. error.timedout = Timed out!\nMake sure the host has port forwarding set up, and that the address is correct! @@ -323,6 +346,7 @@ error.alreadyconnected = Already connected. error.mapnotfound = Map file not found! error.io = Network I/O error. error.any = Unknown network error. +error.bloom = Failed to initialize bloom.\nYour device may not support it. zone.groundZero.name = Ground Zero zone.desertWastes.name = Desert Wastes @@ -334,6 +358,23 @@ zone.desolateRift.name = Desolate Rift zone.nuclearComplex.name = Nuclear Production Complex zone.overgrowth.name = Overgrowth zone.tarFields.name = Tar Fields +zone.saltFlats.name = Salt Flats +zone.impact0078.name = Impact 0078 +zone.crags.name = Crags + +zone.groundZero.description = The optimal location to begin once more. Low enemy threat. Few resources.\nGather as much lead and copper as possible.\nMove on. +zone.frozenForest.description = Even here, closer to mountains, the spores have spread. The fridgid temperatures cannot contains them forever.\n\nBegin the venture into power. Build combustion generators. Learn to use menders. +zone.desertWastes.description = These wastes are vast, unpredictable, and criss-crossed with derelict sector structures.\nCoal is present in the region. Burn it for power, or synthesize graphite.\n\n[lightgray]This landing location cannot be guaranteed. +zone.saltFlats.description = On the outskirts of the desert lie the Salt Flats. Few resources can be found in this location.\n\nThe enemy has erected a resource storage complex here. Eradicate their core. Leave nothing standing. +zone.craters.description = Water has accumulated in this crater, relic of the old wars. Reclaim the area. Collect sand. Smelt metaglass. Pump water to cool turrets and drills. +zone.ruinousShores.description = Past the wastes, is the shoreline. Once, this location housed a coastal defense array. Not much of it remains. Only the most basic defense structures have remained unscathed, everything else reduced to scrap.\nContinue the expansion outwards. Rediscover the technology. +zone.stainedMountains.description = Further inland lie the mountains, yet untainted by spores.\nExtract the abundant titanium in this area. Learn how to use it.\n\nThe enemy presence is greater here. Do not give them time to send their strongest units. +zone.overgrowth.description = This area is overgrown, closer to the source of the spores.\nThe enemy has established an outpost here. Build dagger units. Destroy it. Reclaim that which was lost. +zone.tarFields.description = The outskirts of an oil production zone, between the mountains and desert. One of the few areas with usable tar reserves.\nAlthough abandoned, this area has some dangerous enemy forces nearby. Do not underestimate them.\n\n[lightgray]Research oil processing technology if possible. +zone.desolateRift.description = An extremely dangerous zone. Plentiful resources, but little space. High risk of destruction. Leave as soon as possible. Do not be fooled by the long spacing between enemy attacks. +zone.nuclearComplex.description = A former facility for the production and processing of thorium, reduced to ruins.\n[lightgray]Research the thorium and its many uses.\n\nThe enemy is present here in great numbers, constantly scouting for attackers. +zone.impact0078.description = +zone.crags.description = settings.language = Language settings.reset = Reset to Defaults @@ -353,12 +394,14 @@ no = No info.title = Info error.title = [crimson]An error has occured error.crashtitle = An error has occured +attackpvponly = [scarlet]Only available in Attack/PvP modes blocks.input = Input blocks.output = Output blocks.booster = Booster -block.unknown = [LIGHT_GRAY]??? +block.unknown = [lightgray]??? blocks.powercapacity = Power Capacity blocks.powershot = Power/Shot +blocks.damage = Damage blocks.targetsair = Targets Air blocks.targetsground = Targets Ground blocks.itemsmoved = Move Speed @@ -434,12 +477,14 @@ setting.shadows.name = Shadows setting.linear.name = Linear Filtering setting.animatedwater.name = Animated Water setting.animatedshields.name = Animated Shields -setting.antialias.name = Antialias[LIGHT_GRAY] (requires restart)[] +setting.antialias.name = Antialias[lightgray] (requires restart)[] setting.indicators.name = Enemy/Ally Indicators setting.autotarget.name = Auto-Target +setting.keyboard.name = Mouse+Keyboard Controls setting.fpscap.name = Max FPS setting.fpscap.none = None setting.fpscap.text = {0} FPS +setting.uiscale.name = UI Scaling[lightgray] (require restart)[] setting.swapdiagonal.name = Always Diagonal Placement setting.difficulty.training = Training setting.difficulty.easy = Easy @@ -453,11 +498,11 @@ setting.sensitivity.name = Controller Sensitivity setting.saveinterval.name = Save Interval setting.seconds = {0} Seconds setting.fullscreen.name = Fullscreen -setting.borderlesswindow.name = Borderless Window[LIGHT_GRAY] (may require restart) +setting.borderlesswindow.name = Borderless Window[lightgray] (may require restart) setting.fps.name = Show FPS setting.vsync.name = VSync setting.lasers.name = Show Power Lasers -setting.pixelate.name = Pixelate[LIGHT_GRAY] (disables animations) +setting.pixelate.name = Pixelate[lightgray] (disables animations) setting.minimap.name = Show Minimap setting.musicvol.name = Music Volume setting.mutemusic.name = Mute Music @@ -466,7 +511,11 @@ setting.mutesound.name = Mute Sound setting.crashreport.name = Send Anonymous Crash Reports setting.chatopacity.name = Chat Opacity setting.playerchat.name = Display In-Game Chat +uiscale.reset = UI scale has been changed.\nPress "OK" to confirm this scale.\n[scarlet]Reverting and exiting in[accent] {0}[] settings... +uiscale.cancel = Cancel & Exit +setting.bloom.name = Bloom keybind.title = Rebind Keys +keybinds.mobile = [scarlet]Most keybinds here are not functional on mobile. Only basic movement is supported. category.general.name = General category.view.name = View category.multiplayer.name = Multiplayer @@ -504,18 +553,19 @@ keybind.drop_unit.name = Drop Unit keybind.zoom_minimap.name = Zoom minimap mode.help.title = Description of modes mode.survival.name = Survival -mode.survival.description = The normal mode. Limited resources and automatic incoming waves. +mode.survival.description = The normal mode. Limited resources and automatic incoming waves.\n[gray]Requires enemy spawns in the map to play. mode.sandbox.name = Sandbox mode.sandbox.description = Infinite resources and no timer for waves. mode.pvp.name = PvP -mode.pvp.description = Fight against other players locally. Requires at least 2 differently-colored cores in the map to play. +mode.pvp.description = Fight against other players locally.\n[gray]Requires at least 2 differently-colored cores in the map to play. mode.attack.name = Attack -mode.attack.description = Destroy the enemy's base. No waves. Requires a red core in the map to play. +mode.attack.description = Destroy the enemy's base. No waves.\n[gray]Requires a red core in the map to play. mode.custom = Custom Rules rules.infiniteresources = Infinite Resources rules.wavetimer = Wave Timer rules.waves = Waves +rules.attack = Attack Mode rules.enemyCheat = Infinite AI (Red Team) Resources rules.unitdrops = Unit Drops rules.unitbuildspeedmultiplier = Unit Production Speed Multiplier @@ -523,13 +573,13 @@ rules.unithealthmultiplier = Unit Health Multiplier rules.playerhealthmultiplier = Player Health Multiplier rules.playerdamagemultiplier = Player Damage Multiplier rules.unitdamagemultiplier = Unit Damage Multiplier -rules.enemycorebuildradius = Enemy Core No-Build Radius:[LIGHT_GRAY] (tiles) -rules.respawntime = Respawn Time:[LIGHT_GRAY] (sec) -rules.wavespacing = Wave Spacing:[LIGHT_GRAY] (sec) +rules.enemycorebuildradius = Enemy Core No-Build Radius:[lightgray] (tiles) +rules.respawntime = Respawn Time:[lightgray] (sec) +rules.wavespacing = Wave Spacing:[lightgray] (sec) rules.buildcostmultiplier = Build Cost Multiplier rules.buildspeedmultiplier = Build Speed Multiplier rules.waitForWaveToEnd = Waves wait for enemies -rules.dropzoneradius = Drop Zone Radius:[LIGHT_GRAY] (tiles) +rules.dropzoneradius = Drop Zone Radius:[lightgray] (tiles) rules.respawns = Max respawns per wave rules.limitedRespawns = Limit Respawns rules.title.waves = Waves @@ -545,36 +595,21 @@ content.unit.name = Units content.block.name = Blocks content.mech.name = Mechs item.copper.name = Copper -item.copper.description = A useful structure material. Used extensively in all types of blocks. item.lead.name = Lead -item.lead.description = A basic starter material. Used extensively in electronics and liquid transportation blocks. item.coal.name = Coal -item.coal.description = A common and readily available fuel. item.graphite.name = Graphite item.titanium.name = Titanium -item.titanium.description = A rare super-light metal used extensively in liquid transportation, drills and aircraft. item.thorium.name = Thorium -item.thorium.description = A dense, radioactive metal used as structural support and nuclear fuel. item.silicon.name = Silicon -item.silicon.description = An extremely useful semiconductor, with applications in solar panels and many complex electronics. item.plastanium.name = Plastanium -item.plastanium.description = A light, ductile material used in advanced aircraft and fragmentation ammunition. item.phase-fabric.name = Phase Fabric -item.phase-fabric.description = A near-weightless substance used in advanced electronics and self-repairing technology. item.surge-alloy.name = Surge Alloy -item.surge-alloy.description = An advanced alloy with unique electrical properties. item.spore-pod.name = Spore Pod -item.spore-pod.description = Used for conversion into oil, explosives and fuel. item.sand.name = Sand -item.sand.description = A common material that is used extensively in smelting, both in alloying and as a flux. item.blast-compound.name = Blast Compound -item.blast-compound.description = A volatile compound used in bombs and explosives. While it can burned as fuel, this is not advised. item.pyratite.name = Pyratite -item.pyratite.description = An extremely flammable substance used in incendiary weapons. item.metaglass.name = Metaglass -item.metaglass.description = A super-tough glass compound. Extensively used for liquid distribution and storage. item.scrap.name = Scrap -item.scrap.description = Leftover remnants of old structures and units. Contains trace amounts of many different metals. liquid.water.name = Water liquid.slag.name = Slag liquid.oil.name = Oil @@ -582,48 +617,41 @@ liquid.cryofluid.name = Cryofluid mech.alpha-mech.name = Alpha mech.alpha-mech.weapon = Heavy Repeater mech.alpha-mech.ability = Regeneration -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 -mech.delta-mech.description = A fast, lightly-armored mech made for hit-and-run attacks. Does little damage against structures, but can kill large groups of enemy units very quickly with its arc lightning weapons. mech.tau-mech.name = Tau mech.tau-mech.weapon = Restruct Laser mech.tau-mech.ability = Repair Burst -mech.tau-mech.description = The support mech. Heals allied blocks by shooting at them. Can heal allies in a radius with its repair ability. mech.omega-mech.name = Omega mech.omega-mech.weapon = Swarm Missiles mech.omega-mech.ability = Armored Configuration -mech.omega-mech.description = A bulky and well-armored mech, made for front-line assaults. Its armor ability can block up to 90% of incoming damage. mech.dart-ship.name = Dart mech.dart-ship.weapon = Repeater -mech.dart-ship.description = The standard ship. Reasonably fast and light, but has little offensive capability and low mining speed. mech.javelin-ship.name = Javelin -mech.javelin-ship.description = A hit-and-run strike ship. While initially slow, it can accelerate to great speeds and fly by enemy outposts, dealing large amounts of damage with its lightning ability and missiles. mech.javelin-ship.weapon = Burst Missiles mech.javelin-ship.ability = Discharge Booster mech.trident-ship.name = Trident -mech.trident-ship.description = A heavy bomber. Reasonably well armored. mech.trident-ship.weapon = Bomb Bay mech.glaive-ship.name = Glaive -mech.glaive-ship.description = A large, well-armored gunship. Equipped with an incendiary repeater. Good acceleration and maximum speed. mech.glaive-ship.weapon = Flame Repeater -item.explosiveness = [LIGHT_GRAY]Explosiveness: {0}% -item.flammability = [LIGHT_GRAY]Flammability: {0}% -item.radioactivity = [LIGHT_GRAY]Radioactivity: {0}% -unit.health = [LIGHT_GRAY]Health: {0} -unit.speed = [LIGHT_GRAY]Speed: {0} -mech.weapon = [LIGHT_GRAY]Weapon: {0} -mech.health = [LIGHT_GRAY]Health: {0} -mech.itemcapacity = [LIGHT_GRAY]Item Capacity: {0} -mech.minespeed = [LIGHT_GRAY]Mining Speed: {0}% -mech.minepower = [LIGHT_GRAY]Mining Power: {0} -mech.ability = [LIGHT_GRAY]Ability: {0} -mech.buildspeed = [LIGHT_GRAY]Building Speed: {0}% -liquid.heatcapacity = [LIGHT_GRAY]Heat Capacity: {0} -liquid.viscosity = [LIGHT_GRAY]Viscosity: {0} -liquid.temperature = [LIGHT_GRAY]Temperature: {0} +item.explosiveness = [lightgray]Explosiveness: {0}% +item.flammability = [lightgray]Flammability: {0}% +item.radioactivity = [lightgray]Radioactivity: {0}% +unit.health = [lightgray]Health: {0} +unit.speed = [lightgray]Speed: {0} +mech.weapon = [lightgray]Weapon: {0} +mech.health = [lightgray]Health: {0} +mech.itemcapacity = [lightgray]Item Capacity: {0} +mech.minespeed = [lightgray]Mining Speed: {0}% +mech.minepower = [lightgray]Mining Power: {0} +mech.ability = [lightgray]Ability: {0} +mech.buildspeed = [lightgray]Building Speed: {0}% +liquid.heatcapacity = [lightgray]Heat Capacity: {0} +liquid.viscosity = [lightgray]Viscosity: {0} +liquid.temperature = [lightgray]Temperature: {0} +block.sand-boulder.name = Sand Boulder block.grass.name = Grass block.salt.name = Salt block.saltrocks.name = Salt Rocks @@ -634,6 +662,7 @@ block.spore-pine.name = Spore Pine block.sporerocks.name = Spore Rocks block.rock.name = Rock block.snowrock.name = Snow Rock +block.snow-pine.name = Snow Pine block.shale.name = Shale block.shale-boulder.name = Shale Boulder block.moss.name = Moss @@ -646,10 +675,9 @@ 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} [LIGHT_GRAY](Constructing) +block.constructing = {0} [lightgray](Constructing) block.spawn.name = Enemy Spawn block.core-shard.name = Core: Shard block.core-foundation.name = Core: Foundation @@ -715,9 +743,7 @@ block.junction.name = Junction block.router.name = Router block.distributor.name = Distributor block.sorter.name = Sorter -block.sorter.description = Sorts items. If an item matches the selection, it is allowed to pass. Otherwise, the item is outputted to the left and right. block.overflow-gate.name = Overflow Gate -block.overflow-gate.description = A combination splitter and router that only outputs to the left and right if the front path is blocked. block.silicon-smelter.name = Silicon Smelter block.phase-weaver.name = Phase Weaver block.pulverizer.name = Pulverizer @@ -733,7 +759,7 @@ block.surge-tower.name = Surge Tower block.battery.name = Battery block.battery-large.name = Large Battery block.combustion-generator.name = Combustion Generator -block.turbine-generator.name = Turbine Generator +block.turbine-generator.name = Steam Generator block.differential-generator.name = Differential Generator block.impact-reactor.name = Impact Reactor block.mechanical-drill.name = Mechanical Drill @@ -769,8 +795,9 @@ block.blast-mixer.name = Blast Mixer block.solar-panel.name = Solar Panel block.solar-panel-large.name = Large Solar Panel block.oil-extractor.name = Oil Extractor -block.spirit-factory.name = Spirit Drone Factory -block.phantom-factory.name = Phantom Drone Factory +block.draug-factory.name = Draug Miner Drone Factory +block.spirit-factory.name = Spirit Repair Drone Factory +block.phantom-factory.name = Phantom Builder Drone Factory block.wraith-factory.name = Wraith Fighter Factory block.ghoul-factory.name = Ghoul Bomber Factory block.dagger-factory.name = Dagger Mech Factory @@ -807,7 +834,6 @@ block.spectre.name = Spectre block.meltdown.name = Meltdown block.container.name = Container block.launch-pad.name = Launch Pad -block.launch-pad.description = Launches batches of items without any need for a core launch. block.launch-pad-large.name = Large Launch Pad team.blue.name = blue team.red.name = red @@ -815,34 +841,28 @@ team.orange.name = orange team.none.name = gray team.green.name = green team.purple.name = purple -unit.spirit.name = Spirit Drone -unit.spirit.description = The starter drone unit. Spawns in the core by default. Automatically mines ores and repairs blocks. -unit.phantom.name = Phantom Drone -unit.phantom.description = An advanced drone unit. Automatically mines ores and repairs blocks. Significantly more effective than a spirit drone. +unit.spirit.name = Spirit Repair Drone +unit.draug.name = Draug Miner Drone +unit.phantom.name = Phantom Builder Drone unit.dagger.name = Dagger -unit.dagger.description = A basic ground unit. Useful in swarms. unit.crawler.name = Crawler unit.titan.name = Titan -unit.titan.description = An advanced, armored ground unit. Attacks both ground and air targets. unit.ghoul.name = Ghoul Bomber -unit.ghoul.description = A heavy carpet bomber. unit.wraith.name = Wraith Fighter -unit.wraith.description = A fast, hit-and-run interceptor unit. unit.fortress.name = Fortress -unit.fortress.description = A heavy artillery ground unit. unit.revenant.name = Revenant unit.eruptor.name = Eruptor unit.chaos-array.name = Chaos Array unit.eradicator.name = Eradicator unit.lich.name = Lich unit.reaper.name = Reaper -tutorial.begin = Your mission here is to eradicate the[LIGHT_GRAY] enemy[].\n\nBegin by[accent] mining copper[]. Tap a copper ore vein near your core to do this. +tutorial.begin = Your mission here is to eradicate the[lightgray] enemy[].\n\nBegin by[accent] mining copper[]. Tap a copper ore vein near your core to do this. tutorial.drill = Mining manually is inefficient.\n[accent]Drills []can mine automatically.\nPlace one on a copper vein. tutorial.conveyor = [accent]Conveyors[] are used to transport items to the core.\nMake a line of conveyors from the drill to the core. tutorial.morecopper = More copper is required.\n\nEither mine it manually, or place more drills. -tutorial.turret = Defensive structures must be built to repel the[LIGHT_GRAY] enemy[].\nBuild a duo turret near your base. +tutorial.turret = Defensive structures must be built to repel the[lightgray] enemy[].\nBuild a duo turret near your base. tutorial.drillturret = Duo turrets require[accent] copper ammo []to shoot.\nPlace a drill next to the turret to supply it with mined copper. -tutorial.waves = The[LIGHT_GRAY] enemy[] approaches.\n\nDefend your core for 2 waves. Build more turrets. +tutorial.waves = The[lightgray] enemy[] approaches.\n\nDefend your core for 2 waves. Build more turrets. tutorial.lead = More ores are available. Explore and mine[accent] lead[].\n\nDrag from your unit to the core to transfer resources. tutorial.smelter = Copper and lead are weak metals.\nSuperior[accent] Dense Alloy[] can be created in a smelter.\n\nBuild one. tutorial.densealloy = The smelter will now produce alloy.\nGet some.\nImprove the production if necessary. @@ -856,106 +876,167 @@ tutorial.silicon = Silicon is being produced. Get some.\n\nImproving the product tutorial.daggerfactory = Construct a[accent] dagger mech factory.[]\n\nThis will be used to create attack mechs. tutorial.router = Factories need resources to function.\nCreate a router to split conveyor resources. tutorial.dagger = Link power nodes to the factory.\nOnce requirements are met, a mech will be created.\n\nCreate more drills, generators and conveyors as necessary. -tutorial.battle = The[LIGHT_GRAY] enemy[] has revealed their core.\nDestroy it with your unit and dagger mechs. +tutorial.battle = The[lightgray] enemy[] has revealed their core.\nDestroy it with your unit and dagger mechs. + +item.copper.description = The most basic structural material. Used extensively in all types of blocks. +item.lead.description = A basic starter material. Used extensively in electronics and liquid transportation blocks. +item.metaglass.description = A super-tough glass compound. Extensively used for liquid distribution and storage. +item.graphite.description = Mineralized carbon, used for ammunition and electrical insulation. +item.sand.description = A common material that is used extensively in smelting, both in alloying and as a flux. +item.coal.description = Fossilized plant matter, formed long before the seeding event. Used extensively for fuel and resource production. +item.titanium.description = A rare super-light metal used extensively in liquid transportation, drills and aircraft. +item.thorium.description = A dense, radioactive metal used as structural support and nuclear fuel. +item.scrap.description = Leftover remnants of old structures and units. Contains trace amounts of many different metals. +item.silicon.description = An extremely useful semiconductor. Applications in solar panels, complex electronics and homing turret ammunition. +item.plastanium.description = A light, ductile material used in advanced aircraft and fragmentation ammunition. +item.phase-fabric.description = A near-weightless substance used in advanced electronics and self-repairing technology. +item.surge-alloy.description = An advanced alloy with unique electrical properties. +item.spore-pod.description = A pod of synthetic spores, synthesized from atmospheric concentrations for industrial purposes. Used for conversion into oil, explosives and fuel. +item.blast-compound.description = An unstable compound used in bombs and explosives. Synthesized from spore pods and other volatile substances. Use as fuel is not advised. +item.pyratite.description = An extremely flammable substance used in incendiary weapons. +liquid.water.description = The most useful liquid. Commonly used for cooling machines and waste processing. +liquid.slag.description = Various different types of molten metal mixed together. Can be separated into its constituent minerals, or sprayed at enemy units as a weapon. +liquid.oil.description = A liquid used in advanced material production. Can be converted into coal as fuel, or sprayed and set on fire as a weapon. +liquid.cryofluid.description = An inert, non-corrosive liquid created from water and titanium. Has extremely high head capacity. Extensively used as a coolant. +mech.alpha-mech.description = The standard control mech. Based on a Dagger unit, with upgraded armor and building capabilities. Has more damage output than a Dart ship. +mech.delta-mech.description = A fast, lightly-armored mech made for hit-and-run attacks. Does little damage against structures, but can kill large groups of enemy units very quickly with its arc lightning weapons. +mech.tau-mech.description = The support mech. Heals allied blocks by shooting at them. Can heal allies in a radius with its repair ability. +mech.omega-mech.description = A bulky and well-armored mech, made for front-line assaults. Its armor can block up to 90% of incoming damage. +mech.dart-ship.description = The standard control ship. Reasonably fast and light, but has little offensive capability and low mining speed. +mech.javelin-ship.description = A hit-and-run strike ship. While initially slow, it can accelerate to great speeds and fly by enemy outposts, dealing large amounts of damage with its lightning and missiles. +mech.trident-ship.description = A heavy bomber, built for construction and destroying enemy fortifications. Reasonably well armored. +mech.glaive-ship.description = A large, well-armored gunship. Equipped with an incendiary repeater. Highly maneuverable. +unit.draug.description = A primitive mining drone. Cheap to produce. Expendable. Automatically mines copper and lead in the vicinity. Delivers mined resources to the closest core. +unit.spirit.description = A modified draug drone, designed for repair instead of mining. Automatically fixes any damaged blocks in the area. +unit.phantom.description = An advanced drone unit. Follows users. Assists in block construction. +unit.dagger.description = The most basic ground mech. Cheap to produce. Overwhelming when used in swarms. +unit.crawler.description = A ground unit consisting of a stripped-down frame with high explosives strapped on top. Not particular durable. Explodes on contact with enemies. +unit.titan.description = An advanced, armored ground unit. Attacks both ground and air targets. Equipped with two miniature Scorch-class flamethrowers. +unit.fortress.description = A heavy artillery mech. Equipped with two modified Hail-type cannons for long-range assault on enemy structures and units. +unit.eruptor.description = A heavy mech designed to take down structures. Fires a stream of slag at enemy fortifications, melting them and setting volatiles on fire. +unit.chaos-array.description = +unit.eradicator.description = +unit.wraith.description = A fast, hit-and-run interceptor unit. Targets power generators. +unit.ghoul.description = A heavy carpet bomber. Rips through enemy structures, targeting critital infrastructure. +unit.revenant.description = A heavy, hovering missile array. +unit.lich.description = +unit.reaper.description = +block.graphite-press.description = Compresses chunks of coal into pure sheets of graphite. +block.multi-press.description = An upgraded version of the graphite press. Employs water and power to process coal quickly and efficiently. +block.silicon-smelter.description = Reduces sand with pure coal. Produces silicon. +block.kiln.description = Smelts sand and lead into the compound known as metaglass. Requires small amounts of power to run. +block.plastanium-compressor.description = Produces plastanium from oil and titanium. +block.phase-weaver.description = Synthesizes phase fabric from radioactive thorium and sand. Requires massive amounts of power to function. +block.alloy-smelter.description = Combines titanium, lead, silicon and copper to produce surge alloy. +block.cryofluidmixer.description = Mixes water and fine titanium titanium powder into cryofluid. Essential for thorium reactor usage. +block.blast-mixer.description = Crushes and mixes clusters of spores with pyratite to produce blast compound. +block.pyratite-mixer.description = Mixes coal, lead and sand into highly flammable pyratite. +block.melter.description = Melts down scrap into slag for further processing or usage in wave turrets. +block.separator.description = Separates slag into its mineral components. Outputs the cooled result. +block.spore-press.description = Compresses spore pods under extreme pressure to synthesize oil. +block.pulverizer.description = Crushes scrap into fine sand. +block.coal-centrifuge.description = Solidifes oil into chunks of coal. +block.incinerator.description = Vaporizes any excess item or liquid it receives. +block.power-void.description = Voids all power inputted into it. Sandbox only. +block.power-source.description = Infinitely outputs power. Sandbox only. +block.item-source.description = Infinitely outputs items. Sandbox only. +block.item-void.description = Destroys any items. Sandbox only. +block.liquid-source.description = Infinitely outputs liquids. Sandbox only. block.copper-wall.description = A cheap defensive block.\nUseful for protecting the core and turrets in the first few waves. block.copper-wall-large.description = A cheap defensive block.\nUseful for protecting the core and turrets in the first few waves.\nSpans multiple tiles. -block.thorium-wall.description = A strong defensive block.\nGood protection from enemies. -block.thorium-wall-large.description = A strong defensive block.\nGood protection from enemies.\nSpans multiple tiles. -block.phase-wall.description = Not as strong as a thorium wall but will deflect bullets unless they are too powerful. -block.phase-wall-large.description = Not as strong as a thorium wall but will deflect bullets unless they are too powerful.\nSpans multiple tiles. -block.surge-wall.description = The strongest defensive block.\nHas a small chance of triggering lightning towards the attacker. -block.surge-wall-large.description = The strongest defensive block.\nHas a small chance of triggering lightning towards the attacker.\nSpans multiple tiles. -block.door.description = A small door that can be opened and closed by tapping on it.\nIf opened, enemies can shoot and move through. -block.door-large.description = A large door that can be opened and closed by tapping on it.\nIf opened, enemies can shoot and move through.\nSpans multiple tiles. -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.titanium-wall.description = A moderately strong defensive block.\nProvides moderate protection from enemies. +block.titanium-wall-large.description = A moderately strong defensive block.\nProvides moderate protection from enemies.\nSpans multiple tiles. +block.thorium-wall.description = A strong defensive block.\nDecent protection from enemies. +block.thorium-wall-large.description = A strong defensive block.\nDecent protection from enemies.\nSpans multiple tiles. +block.phase-wall.description = A wall coated with special phase-based reflective compound. Deflects most bullets upon impact. +block.phase-wall-large.description = A wall coated with special phase-based reflective compound. Deflects most bullets upon impact.\nSpans multiple tiles. +block.surge-wall.description = An extremely durable defensive block.\nBuilds up charge on bullet contact, releasing it randomly. +block.surge-wall-large.description = An extremely durable defensive block.\nBuilds up charge on bullet contact, releasing it randomly.\nSpans multiple tiles. +block.door.description = A small door. Can be opened or closed by tapping. +block.door-large.description = A large door. Can be opened and closed by tapping.\nSpans multiple tiles. +block.mender.description = Periodically repairs blocks in its vicinity. Keeps defenses repaired in-between waves.\nOptionally uses silicon to boost range and efficiency. +block.mend-projector.description = An upgraded version of the Mender. Repairs blocks in its vicinity.\nOptionally uses phase fabric to boost range and efficiency. +block.overdrive-projector.description = Increases the speed of nearby buildings.\nOptionally uses phase fabric to boost range and efficiency. +block.force-projector.description = Creates a hexagonal force field around itself, protecting buildings and units inside from damage.\nOverheats if too much damage is sustained. Optionally requires coolant to prevent overheating. Phase fabric can be used to increase shield size. block.shock-mine.description = Damages enemies stepping on the mine. Nearly invisible to 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. -block.salvo.description = A medium-sized turret which fires shots in salvos. -block.swarmer.description = A medium-sized turret which shoots burst missiles. -block.ripple.description = A large artillery turret which fires several shots simultaneously. -block.cyclone.description = A large rapid fire turret. -block.fuse.description = A large turret which shoots powerful short-range beams. -block.spectre.description = A large turret which shoots two powerful bullets at once. -block.meltdown.description = A large turret which shoots powerful long-range beams. -block.conveyor.description = Basic item transport block. Moves items forward and automatically deposits them into turrets or crafters. Rotatable. +block.conveyor.description = Basic item transport block. Moves items forward and automatically deposits them into blocks. Rotatable. block.titanium-conveyor.description = Advanced item transport block. Moves items faster than standard conveyors. -block.phase-conveyor.description = Advanced item transport block. Uses power to teleport items to a connected phase conveyor over several tiles. block.junction.description = Acts as a bridge for two crossing conveyor belts. Useful in situations with two different conveyors carrying different materials to different locations. -block.mass-driver.description = Ultimate item transport block. Collects several items and then shoots them to another mass driver over a long range. -block.silicon-smelter.description = Reduces sand with highly pure coal in order to produce silicon. -block.plastanium-compressor.description = Produces plastanium from oil and titanium. -block.phase-weaver.description = Produces phase fabric from radioactive thorium and high amounts of sand. -block.alloy-smelter.description = Produces surge alloy from titanium, lead, silicon and copper. -block.pulverizer.description = Crushes scrap into sand. Useful when there is a lack of natural sand. -block.pyratite-mixer.description = Mixes coal, lead and sand into highly flammable pyratite. -block.blast-mixer.description = Uses oil for transforming pyratite into the less flammable but more explosive blast compound. -block.cryofluidmixer.description = Combines water and titanium into cryofluid which is much more efficient for cooling. -block.melter.description = Melts down scrap into slag for further processing or usage in turrets. -block.incinerator.description = Gets rid of any excess item or liquid. -block.spore-press.description = Compresses spore pods into oil. -block.separator.description = Extracts useful minerals from slag. -block.power-node.description = Transmits power to connected nodes. Up to four power sources, sinks or nodes can be connected. The node will receive power from or supply power to any adjacent blocks. -block.power-node-large.description = Has a larger radius than the power node and connects to up to six power sources, sinks or nodes. -block.battery.description = Stores power whenever there is an abundance and provides power whenever there is a shortage, as long as there is capacity left. -block.battery-large.description = Stores much more power than a regular battery. -block.combustion-generator.description = Generates power by burning oil or flammable materials. -block.turbine-generator.description = More efficient than a combustion generator, but requires additional water. -block.thermal-generator.description = Generates power when placed in hot locations. -block.solar-panel.description = Provides a small amount of power from the sun. -block.solar-panel-large.description = Provides much better power supply than a standard solar panel, but is also much more expensive to build. -block.thorium-reactor.description = Generates huge amounts of power from highly radioactive thorium. Requires constant cooling. Will explode violently if insufficient amounts of coolant are supplied. Power output depends on fullness, with base power generated at full capacity. -block.rtg-generator.description = A radioisotope thermoelectric generator which does not require cooling but provides less power than a thorium reactor. -block.unloader.description = Unloads items from a container, vault or core onto a conveyor or directly into an adjacent block. The type of item to be unloaded can be changed by tapping on the unloader. -block.container.description = Stores a small amount of items of each type. An[LIGHT_GRAY] unloader[] can be used to retrieve items from the container. -block.vault.description = Stores a large amount of items of each type. An[LIGHT_GRAY] unloader[] can be used to retrieve items from the vault. -block.mechanical-drill.description = A cheap drill. When placed on appropriate tiles, outputs items at a slow pace indefinitely. -block.pneumatic-drill.description = An improved drill which is faster and able to process harder materials by making use of air pressure. -block.laser-drill.description = Allows drilling even faster through laser technology, but requires power. Additionally, radioactive thorium can be retrieved with this drill. -block.blast-drill.description = The ultimate drill. Requires large amounts of power. -block.water-extractor.description = Extracts water from the ground. Use it when there is no lake nearby. -block.cultivator.description = Cultivates tiny concentrations of spores into industry-ready pods. -block.oil-extractor.description = Uses large amounts of power in order to extract oil from sand. Use it when there is no direct source of oil nearby. -block.trident-ship-pad.description = Leave your current vessel and change into a reasonably well armored heavy bomber.\nUse the pad by double tapping while standing on it. -block.javelin-ship-pad.description = Leave your current vessel and change into a strong and fast interceptor with lightning weapons.\nUse the pad by double tapping while standing on it. -block.glaive-ship-pad.description = Leave your current vessel and change into a large, well-armored gunship.\nUse the pad by double tapping while standing on it. -block.tau-mech-pad.description = Leave your current vessel and change into a support mech which can heal friendly buildings and units.\nUse the pad by double tapping while standing on it. -block.delta-mech-pad.description = Leave your current vessel and change into a fast, lightly-armored mech made for hit-and-run attacks.\nUse the pad by double tapping while standing on it. -block.omega-mech-pad.description = Leave your current vessel and change into a bulky and well-armored mech, made for front-line assaults.\nUse the pad by double tapping while standing on it. -block.spirit-factory.description = Produces light drones which mine ore and repair blocks. -block.phantom-factory.description = Produces advanced drone units which are significantly more effective than a spirit drone. -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. -block.conduit.description = Basic liquid transport block. Works like a conveyor, but with liquids. Best used with extractors, pumps or other conduits. -block.pulse-conduit.description = Advanced liquid transport block. Transports liquids faster and stores more than standard conduits. -block.phase-conduit.description = Advanced liquid transport block. Uses power to teleport liquids to a connected phase conduit over several tiles. +block.bridge-conveyor.description = Advanced item transport block. Allows transporting items over up to 3 tiles of any terrain or building. +block.phase-conveyor.description = Advanced item transport block. Uses power to teleport items to a connected phase conveyor over several tiles. +block.sorter.description = Sorts items. If an item matches the selection, it is allowed to pass. Otherwise, the item is outputted to the left and right. +block.router.description = Accepts items from one direction and outputs them to up to 3 other directions equally. Useful for splitting the materials from one source to multiple targets. +block.distributor.description = An advanced router. Splits items to up to 7 other directions equally. +block.overflow-gate.description = A combination splitter and router. Only outputs to the left and right if the front path is blocked. +block.mass-driver.description = The ultimate item transport block. Collects several items and then shoots them to another mass driver over a long range. Requires power to operate. +block.mechanical-pump.description = A cheap pump with slow output, but no power consumption. +block.rotary-pump.description = An advanced pump. Pumps more liquid, but requires power. +block.thermal-pump.description = The ultimate pump. +block.conduit.description = Basic liquid transport block. Moves liquids forward. Used in conjunction with pumps and other conduits. +block.pulse-conduit.description = An advanced liquid transport block. Transports liquids faster and stores more than standard conduits. block.liquid-router.description = Accepts liquids from one direction and outputs them to up to 3 other directions equally. Can also store a certain amount of liquid. Useful for splitting the liquids from one source to multiple targets. -block.liquid-tank.description = Stores a large amount of liquids. Use it for creating buffers when there is a non-constant demand of materials or as a safeguard for cooling vital blocks. +block.liquid-tank.description = Stores a large amount of liquids. Use for creating buffers in situations with non-constant demand of materials or as a safeguard for cooling vital blocks. block.liquid-junction.description = Acts as a bridge for two crossing conduits. Useful in situations with two different conduits carrying different liquids to different locations. block.bridge-conduit.description = Advanced liquid transport block. Allows transporting liquids over up to 3 tiles of any terrain or building. -block.mechanical-pump.description = A cheap pump with slow output, but no power consumption. -block.rotary-pump.description = An advanced pump which doubles up speed by using power. -block.thermal-pump.description = The ultimate pump. -block.router.description = Accepts items from one direction and outputs them to up to 3 other directions equally. Useful for splitting the materials from one source to multiple targets. -block.distributor.description = An advanced router which splits items to up to 7 other directions equally. -block.bridge-conveyor.description = Advanced item transport block. Allows transporting items over up to 3 tiles of any terrain or building. -block.item-source.description = Infinitely outputs items. Sandbox only. -block.liquid-source.description = Infinitely outputs liquids. Sandbox only. -block.item-void.description = Destroys any items which go into it without using power. Sandbox only. -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. +block.phase-conduit.description = Advanced liquid transport block. Uses power to teleport liquids to a connected phase conduit over several tiles. +block.power-node.description = Transmits power to connected nodes. Up to four power sources, sinks or nodes can be connected. The node will receive power from or supply power to any adjacent blocks. +block.power-node-large.description = An advanced power node with greater range and more connections. +block.surge-tower.description = An extremely long-range power node with fewer available connections. +block.battery.description = Stores power as a buffer in times of surplus energy. Outputs power in times of deficit. +block.battery-large.description = Stores much more power than a regular battery. +block.combustion-generator.description = Generates power by burning flammable materials, such as coal. +block.thermal-generator.description = Generates power when placed in hot locations. +block.turbine-generator.description = An advanced combustion generator. More efficient, but requires additional water for generating steam. +block.differential-generator.description = Generates large amount of energy. Utilizes the temperature difference between cryofluid and burning pyratite. +block.rtg-generator.description = A simple, reliable generator. Uses the heat of decaying radioactive compounds to produce energy at a slow rate. +block.solar-panel.description = Provides a small amount of power from the sun. +block.solar-panel-large.description = A significantly more efficient version of the standard solar panel. +block.thorium-reactor.description = Generates significant amounts of power from thorium. Requires constant cooling. Will explode violently if insufficient amounts of coolant are supplied. Power output depends on fullness, with base power generated at full capacity. +block.impact-reactor.description = An advanced generator, capable of creating massive amounts of power at peak efficiency. Requires a significant power input to kickstart the process. +block.mechanical-drill.description = A cheap drill. When placed on appropriate tiles, outputs items at a slow pace indefinitely. Only capable of mining copper, lead and coal. +block.pneumatic-drill.description = An improved drill, capable of mining titanium. Mines at a faster pace than a mechanical drill. +block.laser-drill.description = Allows drilling even faster through laser technology, but requires power. Capable of mining thorium. +block.blast-drill.description = The ultimate drill. Requires large amounts of power. +block.water-extractor.description = Extracts groundwater. Used in locations with no surface water available. +block.cultivator.description = Cultivates tiny concentrations of spores in the atmosphere into industry-ready pods. +block.oil-extractor.description = Uses large amounts of power, sand and water to drill for oil. +block.core-shard.description = The first iteration of the core capsule. Once destroyed, all contact to the region is lost. Do not let this happen. +block.core-foundation.description = The second version of the core. Better armored. Stores more resources. +block.core-nucleus.description = The third and final iteration of the core capsule. Extremely well armored. Stores massive amounts of resources. +block.vault.description = Stores a large amount of items of each type. An unloader block can be used to retrieve items from the vault. +block.container.description = Stores a small amount of items of each type. An unloader block can be used to retrieve items from the container. +block.unloader.description = Unloads items from a container, vault or core onto a conveyor or directly into an adjacent block. The type of item to be unloaded can be changed by tapping. +block.launch-pad.description = Launches batches of items without any need for a core launch. +block.launch-pad-large.description = An improved version of the launch pad. Stores more items. Launches more frequently. +block.duo.description = A small, cheap turret. Useful against ground units. +block.scatter.description = An essential anti-air turret. Sprays clumps of lead or scrap flak at enemy units. +block.scorch.description = Burns any ground enemies close to it. Highly effective at close range. +block.hail.description = A small, long-range artillery turret. +block.wave.description = A medium-sized turret. Shoots streams of liquid at enemies. Automatically extinguishes fires when supplied with water. +block.lancer.description = A medium-sized anti-ground laser turret. Charges and fires powerful beams of energy. +block.arc.description = A small close-range electrict turret. Fires arcs of electricity at enemies. +block.swarmer.description = A medium-sized missile turret. Attacks both air and ground enemies. Fires homing missiles. +block.salvo.description = A larger, more advanced version of the Duo turret. Fires quick salvos of bullets at the enemy. +block.fuse.description = A large, close-range energy turret. Fires three piercing beams at nearby enemies. +block.ripple.description = An extremely poweful artillery turret. Shoots clusters of shells at enemies over long distances. +block.cyclone.description = A large anti-air and anti-ground turret. Fires explosive clumps of flak at nearby units. +block.spectre.description = A massive dual-barreled cannon. Shoots large armor-piercing bullets at air and ground targets. +block.meltdown.description = A massive laser cannon. Charges and fires a presistent laser beam at nearby enemies. Requires coolant to operate. +block.draug-factory.description = Produces Draug mining drones. +block.spirit-factory.description = Produces Spirit structural repair drones. +block.phantom-factory.description = Produces advanced construction drones. +block.wraith-factory.description = Produces fast, hit-and-run interceptor units. +block.ghoul-factory.description = Produces heavy carpet bombers. +block.revenant-factory.description = Produces heavy missile-based units. +block.dagger-factory.description = Produces basic ground units. +block.crawler-factory.description = Produces fast self-destructing swarm units. +block.titan-factory.description = Produces advanced, armored ground units. +block.fortress-factory.description = Produces heavy artillery ground units. +block.repair-point.description = Continuously heals the closest damaged unit in its vicinity. +block.dart-mech-pad.description = Provides transformation into a basic attack mech.\nUse by tapping while standing on it. +block.delta-mech-pad.description = Provides transformation into a lightly armored hit-and-run attack mech.\nUse by tapping while standing on it. +block.tau-mech-pad.description = Provides transformation into an advanced support mech.\nUse by tapping while standing on it. +block.omega-mech-pad.description = Provides transformation into a heavily-armored missile mech.\nUse by tapping while standing on it. +block.javelin-ship-pad.description = Provides transformation into a quick, lightly-armored interceptor.\nUse by tapping while standing on it. +block.trident-ship-pad.description = Provides transformation into a heavy support bomber.\nUse by tapping while standing on it. +block.glaive-ship-pad.description = Provides transformation into a large, well-armored gunship.\nUse by tapping while standing on it. \ No newline at end of file diff --git a/core/assets/bundles/bundle_fr_BE.properties b/core/assets/bundles/bundle_fr_BE.properties index b700208253..212a8a2db5 100644 --- a/core/assets/bundles/bundle_fr_BE.properties +++ b/core/assets/bundles/bundle_fr_BE.properties @@ -191,8 +191,8 @@ editor.mapinfo = Infos sur la carte editor.author = Auteur: editor.description = Description: editor.waves = Vagues: -editor.rules = Rules: -editor.ingame = Edit In-Game +editor.rules = Règles: +editor.ingame = Modifier en jeu waves.title = Vagues waves.remove = Retirer waves.never = @@ -210,15 +210,15 @@ waves.copied = Vagues copiées. editor.default = [LIGHT_GRAY] edit = Modifier... editor.name = Nom: -editor.spawn = Spawn Unit -editor.removeunit = Remove Unit +editor.spawn = Ajouter une unité +editor.removeunit = Retirer l'unité editor.teams = Équipes editor.elevation = Élévation editor.errorload = Erreur lors du chargement du fichier:\n[accent]{0} editor.errorsave = Erreur lors de la sauvegarde du fichier:\n[accent]{0} -editor.errorimage = That's an image, not a map. Don't go around changing extensions expecting it to work.\n\nIf you want to import a legacy map, use the 'import legacy map' button in the editor. -editor.errorlegacy = This map is too old, and uses a legacy map format that is no longer supported. -editor.errorheader = This map file is either not valid or corrupt. +editor.errorimage = C'est une image, pas une carte. Ne changez pas les extensions en espérant que cela fonctionne.\n\nSi vous souhaitez importer une carte, utilisez le bouton "importer une carte" dans l'éditeur. +editor.errorlegacy = Cette carte est trop ancienne et utilise un format de carte qui n'est plus pris en charge. +editor.errorheader = Ce fichier de carte n'est pas valide ou corrompu. editor.errorname = La carte n'a pas de nom! editor.update = Mettre à jour editor.randomize = Randomiser @@ -271,8 +271,8 @@ filter.option.wall = Mur filter.option.ore = Minerai filter.option.floor2 = Sol secondaire filter.option.threshold2 = Seuil secondaire -filter.option.radius = Radius -filter.option.percentile = Percentile +filter.option.radius = Rayon +filter.option.percentile = Centile width = Largeur: height = Hauteur: menu = Menu @@ -373,7 +373,7 @@ blocks.drillspeed = Vitesse de forage de base blocks.boosteffect = Effet boostant blocks.maxunits = Maximum d'unitée active blocks.health = Santé -blocks.buildtime = Build Time +blocks.buildtime = Temps de construction blocks.inaccuracy = Précision blocks.shots = Tirs blocks.reload = Tirs/Seconde @@ -421,7 +421,7 @@ category.shooting = Défense category.optional = Améliorations facultatives setting.landscape.name = Verrouiller la rotation en mode paysage setting.shadows.name = Ombres -setting.linear.name = Linear Filtering +setting.linear.name = Filtrage linéaire setting.animatedwater.name = Eau animée setting.animatedshields.name = Boucliers Animés setting.antialias.name = Antialias[LIGHT_GRAY] (demande le redémarrage de l'appareil)[] @@ -443,7 +443,7 @@ setting.sensitivity.name = Contôle de la sensibilité setting.saveinterval.name = Intervalle des sauvegardes auto setting.seconds = {0} Secondes setting.fullscreen.name = Plein écran -setting.borderlesswindow.name = Borderless Window[LIGHT_GRAY] (may require restart) +setting.borderlesswindow.name = Fenêtre sans bordure[LIGHT_GRAY] (peut nécessiter un redémarrage) setting.fps.name = Afficher FPS setting.vsync.name = VSync setting.lasers.name = Afficher les rayons des lasers diff --git a/core/assets/bundles/bundle_in_ID.properties b/core/assets/bundles/bundle_in_ID.properties index 62b475ee78..f346a1f211 100644 --- a/core/assets/bundles/bundle_in_ID.properties +++ b/core/assets/bundles/bundle_in_ID.properties @@ -1,947 +1,955 @@ -credits.text = Created by [ROYAL]Anuken[] - [SKY]anukendev@gmail.com[]\n\n[GRAY](In case you can't tell, this text is currently unfinished.\nTranslators, don't edit it yet!) +credits.text = Diciptakan oleh [ROYAL]Anuken[] - [SKY]anukendev@gmail.com[] credits = Kredit -contributors = Translators and Contributors -discord = Mari bergabung di Discord Mindustry! -link.discord.description = grup Discord Mindustry resmi -link.github.description = Source code permainan -link.dev-builds.description = Bentukan pengembang (kurang stabil) -link.trello.description = Papan trello resmi untuk fitur-fitur terencana -link.itch.io.description = Halaman itch.io dengan unduhan PC dan versi web -link.google-play.description = Google Play store -link.wiki.description = wiki resmi Mindustry -linkfail = Gagal membuka link!\nURL telah disalin ke papan salin. -screenshot = Screenshot saved to {0} -screenshot.invalid = Map too large, potentially not enough memory for screenshot. -gameover = Intinya hancur. -gameover.pvp = Tim [accent] {0}[] menang! -highscore = [YELLOW]Rekor baru! -stat.wave = Waves Defeated:[accent] {0} -stat.enemiesDestroyed = Enemies Destroyed:[accent] {0} -stat.built = Buildings Built:[accent] {0} -stat.destroyed = Buildings Destroyed:[accent] {0} -stat.deconstructed = Buildings Deconstructed:[accent] {0} -stat.delivered = Resources Launched: -stat.rank = Final Rank: [accent]{0} -placeline = You have selected a block.\nYou can[accent] place in a line[] by[accent] holding down your finger for a few seconds[] and dragging in a direction.\nTry it. -removearea = You have selected removal mode.\nYou can[accent] remove blocks in a rectangle[] by[accent] holding down your finger for a few seconds[] and dragging.\nTry it. -launcheditems = [accent]Launched Items -map.delete = Apakah kamu yakin ingin menghapus peta "[orange]{0}[]"? -level.highscore = Skor Tinggi: [accent]{0} +contributors = Translator dan Kontributor +discord = Bergabung di Discord Mindustry! +link.discord.description = Discord Mindustry resmi +link.github.description = Sumber kode permainan +link.dev-builds.description = Bentuk pengembangan (kurang stabil) +link.trello.description = Papan Trello resmi untuk fitur terencana +link.itch.io.description = Halaman itch.io dengan PC download dan versi web +link.google-play.description = Google Play Store +link.wiki.description = Wiki Mindustry resmi +linkfail = Gagal membuka tautan!\nURL disalin ke papan ke papan klip. +screenshot = Tangkapan layar disimpan di {0} +screenshot.invalid = Peta terlalu besar, tidak cukp memori untuk menangkap layar. +gameover = Permainan Habis +gameover.pvp = Tim[accent] {0}[] menang! +highscore = [accent]Rekor Baru! + +stat.wave = Gelombang Terkalahkan:[accent] {0} +stat.enemiesDestroyed = Musuh Terhancurkan:[accent] {0} +stat.built = Jumlah Blok yang Dibangun:[accent] {0} +stat.destroyed = Jumlah Blok Dihancurkan Musuh:[accent] {0} +stat.deconstructed = Jumlah Blok Dihancurkan Pemain:[accent] {0} +stat.delivered = Sumber Daya yang Diluncurkan: +stat.rank = Nilai Akhir: [accent]{0} + +placeline = Anda telah memilih sebuah blok.\nAnda bisa[accent] menaruhnya berjejeran[] dengan[accent] menekan layar beberapa saat[] dan menarik jarimu ke arah yang dituju.\n\n[scarlet]Cobalah. +removearea = Anda telah memilih mode penghancuran.\nAnda bisa[accent] menghancurkan blok dalam sebuah kotak[] dengan[accent] menekan layar beberapa saat[] dan menarik jarimu sampai membentuk sebuah area.\n\n[scarlet]Cobalah. + +launcheditems = [accent]Sumber Daya +map.delete = Apakah Anda yakin ingin menghapus peta "[accent]{0}[]"? +level.highscore = Nilai Tertinggi: [accent]{0} level.select = Pilih Level -level.mode = Modus permainan: -showagain = Jangan tampilkan lagi di sesi berikutnya -coreattack = < Intinya sedang diserang! > -nearpoint = [[ [scarlet]LEAVE DROP POINT IMMEDIATELY[] ]\nannihilation imminent -outofbounds = [[ OUT OF BOUNDS ]\n[]self-destruct in {0} -database = Core Database +level.mode = Mode Permainan: +showagain = Jangkan tampilkan lagi di sesi berikutnya +coreattack = < Inti sedang diserang! > +nearpoint = [[ [scarlet]TINGGALKAN TITIK JATUH SEGERA[] ]\npenghancuran akan terjadi +outofbounds = [[ MELEBIHI BATAS ]\n[]penghancuran diri di {0} +database = Basis Data Inti savegame = Simpan Permainan -loadgame = Lanjutkan +loadgame = Muat Permainan joingame = Bermain Bersama -addplayers = Tambah/Hapus Pemain -customgame = Game Bebas -newgame = New Game +addplayers = Tambah/Menghapus Pemain +customgame = Permainan Modifikasi +newgame = Permainan Baru none = -minimap = Minimap +minimap = Peta Kecil close = Tutup quit = Keluar -maps = Peta continue = Lanjutkan -maps.none = [LIGHT_GRAY]Peta tidak ditemukan! +maps.none = [LIGHT_GRAY]Tidak ketemu peta! about.button = Tentang name = Nama: -noname = Pick a[accent] player name[] first. -filename = Nama file: -unlocked = Blok Baru Terbuka! -completed = [accent]Completed -techtree = Tech Tree -research.list = [LIGHT_GRAY]Research: -research = Research -researched = [LIGHT_GRAY]{0} researched. -players = {0} pemain online -players.single = {0} pemain online +noname = Pilih[accent] nama pemain[] dahulu. +filename = Nama File: +unlocked = Konten baru terbuka! +completed = [accent]Terselesaikan +research.list = [LIGHT_GRAY]Penelitian: +research = Penelitian +researched = [LIGHT_GRAY]{0} telah diteliti. +players = {0} pemain aktif +players.single = {0} pemain aktif server.closing = [accent]Menutup server... server.kicked.kick = Anda telah dikeluarkan dari server! server.kicked.serverClose = Server ditutup. -server.kicked.clientOutdated = Client versi lama! Update game Anda! -server.kicked.serverOutdated = Server versi lama! Tanyakan host untuk memperbaharuinya! -server.kicked.banned = Anda telah di-ban dari server ini. -server.kicked.recentKick = Kamu baru saja dikeluarkan.\nTunggu sebentar sebelum terhubung kembali. -server.kicked.nameInUse = Ada seseorang dengan nama\nitu di server ini. -server.kicked.nameEmpty = Nama Anda harus mengandung setidaknya satu karakter atau angka. -server.kicked.idInUse = Kamu sudah ada di server ini! Menghubungkan dengan dua akun tidak diizinkan. -server.kicked.customClient = Server ini tidak mendukung bentukan khusus. Unduh versi resmi. +server.kicked.clientOutdated = Client kadaluarsa! perbarui permainan Anda! +server.kicked.serverOutdated = Server kadaluarsa! Tanya host untuk diperbarui! +server.kicked.banned = Anda telah dilarang untuk memasuki server ini. +server.kicked.recentKick = Anda baru saja dikeluarkan dari server ini.\nTunggu sebelum masuk lagi. +server.kicked.nameInUse = Sudah ada pemain dengan nama itu \ndi server ini. +server.kicked.nameEmpty = Nama yang dipilih tidak valid. +server.kicked.idInUse = Anda telah berada di server ini! Memasuki dengan dua akun tidak diizinkan. +server.kicked.customClient = Server ini tidak mendukung versi modifikasi. Download versi resmi. server.kicked.gameover = Game over! -host.info = Tombol [accent]host[] akan membuat server dengan port [scarlet]6567[] dan [scarlet]6568.[]\nSiapa saja yang terhubung ke [LIGHT_GRAY]WiFi atau jaringan lokal[] dapat melihat server Anda di daftar server.\n\nJika Anda ingin orang-orang agar dapat terhubung dari mana saja melalui IP, diperlukan [accent]port forwarding[].\n\n[LIGHT_GRAY]Catatan: Jika seseorang mengalami kesulitan untuk bergabung, pastikan bahwa Anda telah mengizinkan akses Mindustry ke jaringan lokal Anda di pengaturan firewall. -join.info = Di sini, Anda dapat memasukan [accent]IP server[] yang akan dihubungkan, atau menemukan server di [accent]jaringan lokal[] untuk dihubungkan.\nKedua jaringan LAN dan WAN didukung.\n\n[LIGHT_GRAY]Catatan: There is no automatic global server list; if you want to connect to someone by IP, you would need to ask the host for their IP. -hostserver = Host Server +host.info = Tombol [accent]host[] akan membuat server sementara di port [scarlet]6567[]. \nSemua orang yang memiliki [LIGHT_GRAY]Wi-Fi atau jaringan lokal[] akan bisa melihat server anda di daftar server mereka.\n\nJika Anda ingin pemain dari mana saja memasuki servermu dengan IP, [accent]port forwarding[] dibutuhkan.\n\n[LIGHT_GRAY]Diingat: Jika seseorang mengalami masalah memasuki permainan LAN mu, pastikan Anda telah mengizinkan Mindustry akses ke jaringan lokalmu di pengaturan firewall. +join.info = Disini, Anda bisa memasuki [accent]server IP[], atau menemukan [accent]server lokal[] untuk bermain bersama.\nLAN dan WAN mendukung permainan bersama.\n\n[LIGHT_GRAY]Diingat: Tidak ada daftar server global; jika anda ingin bergabung dengan seseorang memakai IP, Anda perlu menanyakan host tentang IP mereka. +hostserver = Host Permainan hostserver.mobile = Host\nPermainan host = Host hosting = [accent]Membuka server... -hosts.refresh = Segarkan -hosts.discovering = Mencari game LAN -server.refreshing = Menyegarkan server -hosts.none = [lightgray]Tidak ada game LAN yang ditemukan! -host.invalid = [scarlet]Tidak dapat terhubung ke host. -trace = Lacak Pemain +hosts.refresh = Muat Ulang +hosts.discovering = Mencari permainan LAN +server.refreshing = Memuat ulang server +hosts.none = [lightgray]Tidak ditemukan game lokal! +host.invalid = [scarlet]Tidak bisa menyambung dengan host. +trace = Melacak Pemain trace.playername = Nama pemain: [accent]{0} trace.ip = IP: [accent]{0} trace.id = ID Unik: [accent]{0} -trace.mobile = Mobile Client: [accent]{0} -trace.modclient = Klien Khusus: [accent]{0} -invalidid = ID klien tidak valid! Kirim laporan bug. -server.bans = Ban -server.bans.none = Tidak ada pemain di-ban! +trace.mobile = Client Mobile: [accent]{0} +trace.modclient = Client Modifikasi: [accent]{0} +invalidid = Client ID tidak valid! laporkan masalah. +server.bans = Pemain Dilarang Masuk +server.bans.none = Tidak ada pemain yang dilarang masuk! server.admins = Admin -server.admins.none = Tidak ada admin yang ditemukan! +server.admins.none = Tidak ada admin! server.add = Tambahkan Server -server.delete = Yakin ingin menghapus server ini? +server.delete = Anda yakin ingin menghapus server ini? server.hostname = Host: {0} server.edit = Sunting Server -server.outdated = [crimson]Server kedaluarsa![] -server.outdated.client = [crimson]Klien kedaluarsa![] -server.version = [lightgray]Versi: {0} -server.custombuild = [yellow]Bentukan khusus -confirmban = Apakah Anda yakin ingin melarang pemain ini? -confirmkick = Apakah Anda yakin ingin mengeluarkan pemain ini? -confirmunban = Apakah Anda yakin ingin mengizinkan pemain ini? -confirmadmin = Apakah Anda yakin ingin menjadikan pemain ini sebagai admin? -confirmunadmin = Are you sure you want to remove admin status from this player? +server.outdated = [crimson]Server Kadaluarsa![] +server.outdated.client = [crimson]Client Kadaluarsa![] +server.version = [lightgray]Versi: {0} {1} +server.custombuild = [yellow]Bentuk Modifikasi +confirmban = Anda yakin ingin melarang pemain ini untuk masuk lagi? +confirmkick = Anda yakin ingin mengeluarkan pemain ini? +confirmunban = Anda yakin ingin mengizinkan pemain ini untuk masuk lagi? +confirmadmin = Anda yakin ingin membuat pemain ini sebagai admin? +confirmunadmin = Anda yakin ingin menghapus status admin dari pemain ini? joingame.title = Bermain Bersama -joingame.ip = IP: -disconnect = Sambungan terputus. -disconnect.data = Failed to load world data! -connecting = [accent]Menghubungkan... -connecting.data = [accent]Memuat data level... +joingame.ip = Alamat: +disconnect = Terputus. +disconnect.data = Gagal memuat data server! +connecting = [accent]Memasuki... +connecting.data = [accent]Memuat data server... server.port = Port: -server.addressinuse = Alamat sudah di pakai! -server.invalidport = Nomor port salah! -server.error = [crimson]Kesalahan server hosting: [accent]{0} -save.old = This save is for an older version of the game, and can no longer be used.\n\n[LIGHT_GRAY]Save backwards compatibility will be implemented in the full 4.0 release. -save.new = Simpan Baru -save.overwrite = Yakin ingin mengganti slot simpan ini? -overwrite = Ganti -save.none = Tidak ada simpanan ditemukan! +server.addressinuse = Alamat sudah ada! +server.invalidport = Nomor port tidak valid! +server.error = [crimson]Error menghosting server: [accent]{0} +save.old = Simpanan ini dari versi yang lama, dan tidak bisa dipakai lagi.\n\n[LIGHT_GRAY]Fitur penyimpanan terbalik akan di implementasikan di versi 4.0 penuh. +save.new = Simpanan Baru +save.overwrite = Anda yakin ingin menindih \ntempat simpanan ini? +overwrite = Tindih +save.none = Tidak ada simpanan! saveload = [accent]Menyimpan... -savefail = Gagal menyimpan game! -save.delete.confirm = Yakin ingin menghapus save ini? +savefail = Gagal menyimpan permainan! +save.delete.confirm = Anda yakin ingin menghapus simpanan ini? save.delete = Hapus save.export = Ekspor Simpanan save.import.invalid = [accent]Simpanan ini tidak valid! -save.import.fail = [crimson]Gagal mengimpor: [accent]{0} -save.export.fail = [crimson]Gagal mengekspor save: [accent]{0} +save.import.fail = [crimson]Gagal mengimpor simpanan: [accent]{0} +save.export.fail = [crimson]Gagal mengekspor simpanan: [accent]{0} save.import = Impor Simpanan -save.newslot = Nama simpanan: +save.newslot = Simpan nama: save.rename = Ganti nama save.rename.text = Nama baru: selectslot = Pilih simpanan. -slot = [accent]Slot{0} -save.corrupted = [accent]Simpanan rusak atau tidak valid! +slot = [accent]Tempat {0} +save.corrupted = [accent]File simpanan rusak atau tidak valid!\nJika Anda baru saja memperbarui permainannya, ini karena perubahan di format penyimpanan dan [scarlet]bukan[] sebuah bug. empty = -on = Hidup -off = Mati -save.autosave = Simpan otomatis: {0} +on = Aktif +off = Nonaktif +save.autosave = Auto simpan: {0} save.map = Peta: {0} save.wave = Gelombang {0} -save.difficulty = Difficulty: {0} -save.date = Terakhir Disimpan: {0} -save.playtime = Playtime: {0} -warning = Warning. +save.difficulty = Tingkat Kesulitan: {0} +save.date = Simpanan Terakhir: {0} +save.playtime = Waktu Bermain: {0} +warning = Peringatan. confirm = Konfirmasi delete = Hapus ok = OK open = Buka -customize = Customize +customize = Modifikasi cancel = Batal -openlink = Buka tautan -copylink = Copy Link +openlink = Buka Tautan +copylink = Salin Tautan back = Kembali -quit.confirm = Anda yakin ingin berhenti? +quit.confirm = Apakah Anda yakin ingin keluar? changelog.title = Changelog -changelog.loading = Getting changelog... -changelog.error.android = [accent]Note that the changelog sometimes does not work on Android 4.4 and below!\nThis is due to an internal Android bug. -changelog.error.ios = [accent]The changelog is currently not supported in iOS. -changelog.error = [scarlet]Error getting changelog!\nCheck your internet connection. -changelog.current = [yellow][[Current version] -changelog.latest = [accent][[Latest version] +changelog.loading = Mendapatkan changelog... +changelog.error.android = [accent]Perlu diingat bahwa terkadang changelog tidak bekerja di Android 4.4 dan kebawah!\nDikarenakan Internal Android bug. +changelog.error.ios = [accent]Changelog saat ini tidak didukung iOS. +changelog.error = [scarlet]Error mendapatkan changelog!\nCek koneksi internetmu. +changelog.current = [yellow][[Versi Sekarang] +changelog.latest = [accent][[Versi Terbaru] loading = [accent]Memuat... -saving = [accent]Saving... +saving = [accent]Menyimpan... wave = [accent]Gelombang {0} -wave.waiting = Gelombang dimulai {0} -wave.waveInProgress = [LIGHT_GRAY]Wave in progress -waiting = Menunggu... -waiting.players = Waiting for players... -wave.enemies = [LIGHT_GRAY]{0} Enemies Remaining -wave.enemy = [LIGHT_GRAY]{0} Enemy Remaining -loadimage = Buka Gambar +wave.waiting = [LIGHT_GRAY]Gelombang di {0} +wave.waveInProgress = [LIGHT_GRAY]Gelombang sedang berlangsung +waiting = [LIGHT_GRAY]Menunggu... +waiting.players = Menunggu pemain lainnya... +wave.enemies = [LIGHT_GRAY]{0} Musuh Tersisa +wave.enemy = [LIGHT_GRAY]{0} Musuh Tersisa +loadimage = Memuat Gambar saveimage = Simpan Gambar -unknown = Unknown -custom = Custom +unknown = Tak diketahui +custom = Modifikasi builtin = Built-In -map.delete.confirm = Are you sure you want to delete this map? This action cannot be undone! -map.random = [accent]Random Map -map.nospawn = This map does not have any cores for the player to spawn in! Add a [ROYAL]blue[] core to this map in the editor. -map.nospawn.pvp = This map does not have any enemy cores for player to spawn into! Add[SCARLET] red[] cores to this map in the editor. -map.nospawn.attack = This map does not have any enemy cores for player to attack! Add[SCARLET] red[] cores to this map in the editor. -map.invalid = Error loading map: corrupted or invalid map file. -editor.brush = Brush -editor.openin = Open In Editor -editor.oregen = Ore Generation -editor.oregen.info = Ore Generation: -editor.mapinfo = Map Info -editor.author = Author: -editor.description = Description: -editor.waves = Waves: -editor.rules = Rules: -editor.ingame = Edit In-Game -waves.title = Waves -waves.remove = Remove -waves.never = -waves.every = every -waves.waves = wave(s) -waves.perspawn = per spawn -waves.to = to +map.delete.confirm = Anda yakin ingin menghapus peta ini? Aksi ini tidak bisa diubah! +map.random = [accent]Peta Acak +map.nospawn = Peta ini tidak memiliki inti agar pemain bisa muncul! Tambahkan inti [ROYAL] biru[] kedalam peta di penyunting. +map.nospawn.pvp = Peta ini tidak memiliki inti agar pemain lawan bisa muncul! Tambahkan inti[SCARLET] selain biru[] kedalam peta di penyunting. +map.nospawn.attack = Peta ini tidak memiliki inti musuh agar pemain bisa menyerang! Tambahkan inti[SCARLET] merah[] kedalam peta di penyunting. +map.invalid = Error memuat peta: rusak atau file peta tidak valid. +editor.brush = Kuas +editor.openin = Buka di Penyunting +editor.oregen = Generasi Sumber Daya +editor.oregen.info = Generasi Sumber Daya: +editor.mapinfo = Info Peta +editor.author = Pencipta: +editor.description = Deskripsi: +editor.waves = Gelombang: +editor.rules = Peraturan: +editor.ingame = Sunting Dalam Permainan +waves.title = Gelombang +waves.remove = Hapus +waves.never = +waves.every = setiap +waves.waves = gelombang +waves.perspawn = per muncul +waves.to = sampai waves.boss = Boss -waves.preview = Preview -waves.edit = Edit... -waves.copy = Copy to Clipboard -waves.load = Load from Clipboard -waves.invalid = Invalid waves in clipboard. -waves.copied = Waves copied. -editor.default = [LIGHT_GRAY] -edit = Edit... -editor.name = Name: -editor.spawn = Spawn Unit -editor.removeunit = Remove Unit -editor.teams = Teams -editor.elevation = Elevation -editor.errorload = Error loading file:\n[accent]{0} -editor.errorsave = Error saving file:\n[accent]{0} -editor.errorimage = That's an image, not a map. Don't go around changing extensions expecting it to work.\n\nIf you want to import a legacy map, use the 'import legacy map' button in the editor. -editor.errorlegacy = This map is too old, and uses a legacy map format that is no longer supported. -editor.errorheader = This map file is either not valid or corrupt. -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 +waves.preview = Pratinjau +waves.edit = Sunting... +waves.copy = Salin ke Papan klip +waves.load = Tempel dari Papan klip +waves.invalid = Gelombang tidak valid di papan klip. +waves.copied = Gelombang tersalin. +editor.default = [LIGHT_GRAY] +edit = Sunting... +editor.name = Nama: +editor.spawn = Munculkan Unit +editor.removeunit = Hapus Unit +editor.teams = Tim +editor.elevation = Ketinggian +editor.errorload = Error memuat file:\n[accent]{0} +editor.errorsave = Error menyimpan file:\n[accent]{0} +editor.errorimage = Itu gambar biasa, bukan peta. Jangan merubah ekstensi dan megharapkan akan berhasil.\n\nJika anda ingin mengimpor peta "Legacy", gunakan tombol 'impor peta legacy ' di penyunting. +editor.errorlegacy = Peta ini terlalu tua, dan memakai format peta "legacy" yang tidak didukung lagi. +editor.errorheader = File peta ini bisa jadi tidak valid atau rusak rusak. +editor.errorname = Peta tidak ada nama. +editor.update = Perbaruan +editor.randomize = Acak +editor.apply = Terapkan +editor.generate = Generasi +editor.resize = Ubah Ukuran +editor.loadmap = Memuat Peta editor.savemap = Simpan Peta -editor.saved = Saved! -editor.save.noname = Your map does not have a name! Set one in the 'map info' menu. -editor.save.overwrite = Your map overwrites a built-in map! Pick a different name in the 'map info' menu. -editor.import.exists = [scarlet]Unable to import:[] a built-in map named '{0}' already exists! -editor.import = Import... -editor.importmap = Import Map -editor.importmap.description = Import an already existing map -editor.importfile = Import File -editor.importfile.description = Import an external map file -editor.importimage = Import Terrain Image -editor.importimage.description = Import an external map image file -editor.export = Export... -editor.exportfile = Export File -editor.exportfile.description = Export a map file -editor.exportimage = Export Terrain Image -editor.exportimage.description = Export a map image file -editor.loadimage = Buka Gambar -editor.saveimage = Simpan Gambar -editor.unsaved = [scarlet]Anda memiliki perubahan yang belum disimpan![]\nYakin ingin keluar? -editor.resizemap = Ubah ukuran peta +editor.saved = Tersimpan! +editor.save.noname = Peta Anda tidak ada nama! Tambahkan di menu 'info peta'. +editor.save.overwrite = Peta ini menindih peta built-in! Pilih nama yang berbeda di menu 'info peta'. +editor.import.exists = [scarlet]Tidak bisa mengimpor:[] peta built-in bernama '{0}' sudah ada! +editor.import = Mengimpor... +editor.importmap = Impor Peta +editor.importmap.description = Mengimpor peta yang telah ada +editor.importfile = Impor File +editor.importfile.description = Mengimpor file peta dari luar +editor.importimage = Impor Peta "Legacy" +editor.importimage.description = Mengimpor peta legacy dari luar +editor.export = Ekspor... +editor.exportfile = Ekspor File +editor.exportfile.description = Mengekspor sebuah file peta +editor.exportimage = Expor Gambar Dunia +editor.exportimage.description = Ekspor sebuah file gambar peta +editor.loadimage = Impor Dunia +editor.saveimage = Ekspor Dunia +editor.unsaved = [scarlet]Anda memiliki perubahan belum disimpan![]\nYakin ingin keluar? +editor.resizemap = Ubah Ukuran Peta 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: -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.chance = Chance -filter.option.mag = Magnitude -filter.option.threshold = Threshold -filter.option.circle-scale = Circle Scale -filter.option.octaves = Octaves -filter.option.falloff = Falloff -filter.option.block = Block -filter.option.floor = Floor -filter.option.wall = Wall -filter.option.ore = Ore -filter.option.floor2 = Secondary Floor -filter.option.threshold2 = Secondary Threshold +editor.overwrite = [accent]Peringatan!\nIni menindih peta yang telah ada. +editor.overwrite.confirm = [scarlet]Peringatan![] Peta dengan nama ini sudah ada. Yakin ingin menindihnya? +editor.selectmap = Pilih peta untuk dimuat: +filters.empty = [LIGHT_GRAY]Tidak ada filter! Tambahkan dengan tombol dibawah. +filter.distort = Rusakkan +filter.noise = Kebisingan +filter.ore = Sumber Daya +filter.rivernoise = Kebisingan Sugnai +filter.scatter = Penebaran +filter.terrain = Lahan +filter.option.scale = Ukuran +filter.option.chance = Kemungkinan +filter.option.mag = Tingkat +filter.option.threshold = Ambang +filter.option.circle-scale = Ukuran Lingkaran +filter.option.octaves = Oktaf +filter.option.falloff = Kemerosotan +filter.option.block = Blok +filter.option.floor = Lantai +filter.option.wall = Dinding +filter.option.ore = Sumber Daya +filter.option.floor2 = Lantai Sekunder +filter.option.threshold2 = Ambang Sekunder filter.option.radius = Radius -filter.option.percentile = Percentile +filter.option.percentile = Perseratus width = Lebar: height = Tinggi: menu = Menu -play = Main -load = Buka +play = Bermain +load = Memuat save = Simpan fps = FPS: {0} tps = TPS: {0} ping = Ping: {0}ms -language.restart = Silakan mulai ulang permainan Anda agar pengaturan bahasa mulai berlaku. +language.restart = Silahkan mengulang kembali permainan agar pengaturan bahasa berpengaruh. settings = Pengaturan tutorial = Tutorial -editor = Pengedit -mapeditor = Pengedit Peta -donate = Sumbangkan -abandon = Abandon -abandon.text = This zone and all its resources will be lost to the enemy. -locked = Locked -complete = [LIGHT_GRAY]Complete: -zone.requirement = Wave {0} in zone {1} -resume = Resume Zone:\n[LIGHT_GRAY]{0} -bestwave = [LIGHT_GRAY]Best: {0} -launch = Launch -launch.title = Launch Successful -launch.next = [LIGHT_GRAY]next opportunity at wave {0} -launch.unable = [scarlet]Unable to LAUNCH.[] Enemies. -launch.confirm = This will launch all resources in your core.\nYou will not be able to return to this base. -uncover = Uncover -configure = Configure Loadout -configure.locked = [LIGHT_GRAY]Reach wave {0}\nto configure loadout. -zone.unlocked = [LIGHT_GRAY]{0} unlocked. -zone.requirement.complete = Wave {0} reached:\n{1} zone requirements met. -zone.config.complete = Wave {0} reached:\nLoadout config unlocked. -zone.resources = Resources Detected: -add = Add... -boss.health = Boss Health -connectfail = [crimson]Gagal terhubung ke server: [accent]{0} -error.unreachable = Server unreachable. -error.invalidaddress = Invalid address. -error.timedout = Timed out!\nMake sure the host has port forwarding set up, and that the address is correct! -error.mismatch = Packet error:\npossible client/server version mismatch.\nMake sure you and the host have the latest version of Mindustry! -error.alreadyconnected = Already connected. -error.mapnotfound = Map file not found! -error.io = Network I/O error. -error.any = Unkown network error. -zone.groundZero.name = Ground Zero -zone.desertWastes.name = Desert Wastes -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 -zone.overgrowth.name = Overgrowth -zone.tarFields.name = Tar Fields +editor = Penyunting +mapeditor = Penyunting Peta +donate = Donasi + +abandon = Tinggalkan +abandon.text = Zona ini dan semua sumber daya didalamnya akan berada di tangan musuh. +locked = Dikunci +complete = [LIGHT_GRAY]Mencapai: +zone.requirement = Gelombang {0} di zona {1} +resume = Lanjutkan Zona:\n[LIGHT_GRAY]{0} +bestwave = [LIGHT_GRAY]Gelombang Terbaik: {0} +launch = < MELUNCUR > +launch.title = Berhasil Meluncur +launch.next = [LIGHT_GRAY]kesempatan berikutnya di gelombang {0} +launch.unable = [scarlet]Tidak bisa MELUNCUR.[] {0} Musuh. +launch.confirm = Ini akan meluncurkan semua sumber daya di inti.\nAnta tidak bisa kembali lagi ke base ini. +uncover = Buka +configure = Konfigurasi Muatan +configure.locked = [LIGHT_GRAY]Buka konfigurasi muatan: Gelombang {0}. +zone.unlocked = [LIGHT_GRAY]{0} terbuka. +zone.requirement.complete = Gelombang {0} terselesaikan:\nPersyaratan zona {1} tercapai. +zone.config.complete = Gelombang {0} terselesaikan:\nkonfigurasi muatan terbuka. +zone.resources = Sumber Daya Terdeteksi: +add = Menambahkan... +boss.health = Darah Boss + +connectfail = [crimson]Gagal menyambung ke server:\n\n[accent]{0} +error.unreachable = Server tak terjangkau.\nApakah alamatnya benar? +error.invalidaddress = Alamat tidak valid. +error.timedout = Waktu Habis!\nPastikan host mempunyai port forwarding, dan alamatnya benar! +error.mismatch = Paket error:\nbisa terjadi apabila versi client/server berbeda.\nPastikan Anda dan host mempunyai versi terbaru Mindustry! +error.alreadyconnected = Sudah tersambung. +error.mapnotfound = File peta tidak ditemaukan! +error.io = Error jaringan I/O. +error.any = Jaringan error tidak diketahui. + +zone.groundZero.name = Titik Nol +zone.desertWastes.name = Gurun Gersang +zone.craters.name = Kawah +zone.frozenForest.name = Hutan Beku +zone.ruinousShores.name = Pantai Hancur +zone.stainedMountains.name = Gunung Bernoda +zone.desolateRift.name = Retakan Terpencil +zone.nuclearComplex.name = Kompleks Produksi Nuklir +zone.overgrowth.name = Pertumbuhan +zone.tarFields.name = Lahan Ter + settings.language = Bahasa -settings.reset = Atur ulang ke Default +settings.reset = Atur ulang ke Default (standar) settings.rebind = Rebind settings.controls = Kontrol settings.game = Permainan settings.sound = Suara -settings.graphics = Grafis -settings.cleardata = Clear Game Data... -settings.clear.confirm = Are you sure you want to clear this data?\nWhat is done cannot be undone! -settings.clearall.confirm = [scarlet]WARNING![]\nThis will clear all data, including saves, maps, unlocks and keybinds.\nOnce you press 'ok' the game will wipe all data and automatically exit. -settings.clearunlocks = Clear Unlocks -settings.clearall = Clear All -paused = Jeda -yes = Yes -no = No -info.title = [accent]Info -error.title = [crimson]Telah terjadi kesalahan -error.crashtitle = Telah terjadi kesalahan -blocks.input = Input -blocks.output = Output +settings.graphics = Grafik +settings.cleardata = Menghapus Data Permainan... +settings.clear.confirm = Anda yakin ingin menghapus data ini?\nWaktu tidak bisa diulang kembali! +settings.clearall.confirm = [scarlet]PERINGATAN![]\nIni akan menghapus semua data permainan, termasuk simpanan, peta, bukaan dan keybind.\nSetelah Anda menekan 'ok' permainan akan menghapus semua data dan keluar otomatis. +settings.clearunlocks = Hapus Bukaan +settings.clearall = Hapus Semua +paused = [accent]< Jeda > +yes = Ya +no = Tidak +info.title = Info +error.title = [crimson]Sebuah error telah terjadi +error.crashtitle = Sebuah error telah terjadi +blocks.input = Masukan +blocks.output = Pengeluaran blocks.booster = Booster block.unknown = [LIGHT_GRAY]??? blocks.powercapacity = Kapasitas Tenaga -blocks.powershot = Tenaga/tembakan -blocks.targetsair = Targets Air -blocks.targetsground = Targets Ground -blocks.itemsmoved = Move Speed -blocks.launchtime = Time Between Launches -blocks.shootrange = Range +blocks.powershot = Tenaga/Tembakan +blocks.targetsair = Menargetkan Udara +blocks.targetsground = Menargetkan Darat +blocks.itemsmoved = Kecepatan Gerak +blocks.launchtime = Waktu Diantara Peluncuran +blocks.shootrange = Jarak blocks.size = Ukuran -blocks.liquidcapacity = Kapasitas cairan -blocks.powerrange = Jangkauan tenaga -blocks.poweruse = Power Use -blocks.powerdamage = Power/Damage -blocks.itemcapacity = Kapasitas Barang -blocks.basepowergeneration = Base Power Generation -blocks.productiontime = Production Time -blocks.repairtime = Block Full Repair Time -blocks.speedincrease = Speed Increase -blocks.range = Range -blocks.drilltier = Drillables -blocks.drillspeed = Base Drill Speed -blocks.boosteffect = Boost Effect -blocks.maxunits = Max Active Units +blocks.liquidcapacity = Kapasitas Zat Cair +blocks.powerrange = Jarak Tenaga +blocks.poweruse = Penggunaan Tenaga +blocks.powerdamage = Tenaga/Pukulan +blocks.itemcapacity = Kapasitas Item +blocks.basepowergeneration = Basis Generasi Tenaga +blocks.productiontime = Waktu Produksi +blocks.repairtime = Waktu Memperbaiki Blok Penuh +blocks.speedincrease = Tambahan Kecepatan +blocks.range = Jarak +blocks.drilltier = Sumber Daya yang Bisa di Bor +blocks.drillspeed = Basis Kecepatan Bor +blocks.boosteffect = Efek Boost +blocks.maxunits = Maks Unit Aktif blocks.health = Darah -blocks.buildtime = Build Time -blocks.inaccuracy = Ketidaktelitian +blocks.buildtime = Waktu Pembuatan +blocks.inaccuracy = Jarak Melenceng blocks.shots = Tembakan -blocks.reload = Reload -blocks.ammo = Ammo -bar.drillspeed = Drill Speed: {0}/s -bar.efficiency = Efficiency: {0}% -bar.powerbalance = Power: {0} -bar.poweramount = Power: {0} -bar.poweroutput = Power Output: {0} -bar.items = Items: {0} -bar.liquid = Liquid -bar.heat = Heat -bar.power = Power -bar.progress = Build Progress -bar.spawned = Units: {0}/{1} -bullet.damage = [stat]{0}[lightgray] dmg -bullet.splashdamage = [stat]{0}[lightgray] area dmg ~[stat] {1}[lightgray] tiles -bullet.incendiary = [stat]incendiary -bullet.homing = [stat]homing -bullet.shock = [stat]shock +blocks.reload = Tembakan/Detik +blocks.ammo = Amunisi + +bar.drillspeed = Kecepatan Bor: {0}/s +bar.efficiency = Daya Guna: {0}% +bar.powerbalance = Tenaga: {0}/s +bar.poweramount = Tenaga: {0} +bar.poweroutput = Pengeluaran Tenaga: {0} +bar.items = Item: {0} +bar.liquid = Zat Cair +bar.heat = Panas +bar.power = Tenaga +bar.progress = Perkembangan Pembangunan +bar.spawned = Unit: {0}/{1} + +bullet.damage = [stat]{0}[lightgray] kekuatan (dmg) +bullet.splashdamage = [stat]{0}[lightgray] area dmg ~[stat] {1}[lightgray] kotak +bullet.incendiary = [stat]pembakar +bullet.homing = [stat]mengejar +bullet.shock = [stat]mengkejut bullet.frag = [stat]frag bullet.knockback = [stat]{0}[lightgray] knockback -bullet.freezing = [stat]freezing -bullet.tarred = [stat]tarred -bullet.multiplier = [stat]{0}[lightgray]x ammo multiplier -bullet.reload = [stat]{0}[lightgray]x reload -unit.blocks = blocks -unit.powersecond = power units/second -unit.liquidsecond = liquid units/second -unit.itemssecond = items/second -unit.liquidunits = liquid units -unit.powerunits = power units -unit.degrees = degrees -unit.seconds = seconds -unit.persecond = /sec -unit.timesspeed = x speed +bullet.freezing = [stat]membeku +bullet.tarred = [stat]tar +bullet.multiplier = [stat]{0}[lightgray]x multiplikasi amunisi +bullet.reload = [stat]{0}[lightgray]x rasio menembak + +unit.blocks = blok +unit.powersecond = unit tenaga/detik +unit.liquidsecond = unit zat cair/detik +unit.itemssecond = item/detik +unit.liquidunits = unit zat cair +unit.powerunits = unit tenaga +unit.degrees = derajat +unit.seconds = detik +unit.persecond = /detik +unit.timesspeed = x kecepatan unit.percent = % -unit.items = items -category.general = General -category.power = Power -category.liquids = Liquids -category.items = Items -category.crafting = Crafting -category.shooting = Shooting -category.optional = Optional Enhancements -setting.landscape.name = Lock Landscape -setting.shadows.name = Shadows -setting.linear.name = Linear Filtering -setting.animatedwater.name = Animated Water -setting.animatedshields.name = Animated Shields -setting.antialias.name = Antialias[LIGHT_GRAY] (requires restart)[] -setting.indicators.name = Ally Indicators +unit.items = item +category.general = Umum +category.power = Tenaga +category.liquids = Zat Cair +category.items = Item +category.crafting = Pemasukan/Pengeluaran +category.shooting = Menembak +category.optional = Peningkatan Opsional +setting.landscape.name = Kunci Pemandangan +setting.shadows.name = Bayangan +setting.linear.name = Linier Filter +setting.animatedwater.name = Animasi Air +setting.animatedshields.name = Animasi Lindungan +setting.antialias.name = Antialiasi[LIGHT_GRAY] (membutuhkan restart)[] +setting.indicators.name = Indikasi Musuh/Teman Lain setting.autotarget.name = Auto-Target -setting.fpscap.name = Max FPS -setting.fpscap.none = None +setting.fpscap.name = Maks FPS +setting.fpscap.none = Tidak Ada setting.fpscap.text = {0} FPS -setting.swapdiagonal.name = Always Diagonal Placement -setting.difficulty.training = training -setting.difficulty.easy = mudah -setting.difficulty.normal = normal -setting.difficulty.hard = sulit -setting.difficulty.insane = sangat susah -setting.difficulty.name = Kesulitan: -setting.screenshake.name = Layar Bergoyang -setting.effects.name = Efek Tampilan -setting.sensitivity.name = Sensitivitas Pengendali -setting.saveinterval.name = Waktu Simpan Otomatis +setting.swapdiagonal.name = Selalu Penaruhan Diagonal +setting.difficulty.training = Latihan +setting.difficulty.easy = Mudah +setting.difficulty.normal = Normal +setting.difficulty.hard = Susah +setting.difficulty.insane = Gila! +setting.difficulty.name = Tingkat Kesulitan: +setting.screenshake.name = Layar Getar +setting.effects.name = Munculkan Efek +setting.sensitivity.name = Sensitivitas Kontroler +setting.saveinterval.name = Jarak Menyimpan setting.seconds = {0} Detik setting.fullscreen.name = Layar Penuh -setting.borderlesswindow.name = Borderless Window[LIGHT_GRAY] (may require restart) +setting.borderlesswindow.name = Jendela tak Berbatas[LIGHT_GRAY] (bisa membutuhkan restart) setting.fps.name = Tunjukkan FPS setting.vsync.name = VSync -setting.lasers.name = Tampilkan Laser Tenaga -setting.pixelate.name = Pixelate [LIGHT_GRAY](may decrease performance) -setting.minimap.name = Show Minimap +setting.lasers.name = Tunjukkan Laser +setting.pixelate.name = Mode Pixel[LIGHT_GRAY] (menonaktifkan animasi) +setting.minimap.name = Tunjukkan Peta kecil setting.musicvol.name = Volume Musik -setting.mutemusic.name = Bisukan Musik -setting.sfxvol.name = Volume Suara -setting.mutesound.name = Bisukan Suara -setting.crashreport.name = Send Anonymous Crash Reports -setting.chatopacity.name = Chat Opacity -setting.playerchat.name = Display In-Game Chat -keybind.title = Rebind Keys -category.general.name = General -category.view.name = View -category.multiplayer.name = Multiplayer -command.attack = Attack -command.retreat = Retreat -command.patrol = Patrol -keybind.gridMode.name = Block Select -keybind.gridModeShift.name = Category Select -keybind.press = Press a key... -keybind.press.axis = Press an axis or key... -keybind.screenshot.name = Map Screenshot -keybind.move_x.name = gerak_x -keybind.move_y.name = gerak_y -keybind.select.name = pilih -keybind.diagonal_placement.name = Diagonal Placement -keybind.pick.name = Pick Block -keybind.break_block.name = Break Block -keybind.deselect.name = Deselect -keybind.shoot.name = tembak -keybind.zoom_hold.name = perbesar_tahan -keybind.zoom.name = perbesar -keybind.menu.name = menu -keybind.pause.name = jeda -keybind.minimap.name = Minimap -keybind.dash.name = berlari -keybind.chat.name = chat -keybind.player_list.name = player_list -keybind.console.name = console -keybind.rotate.name = putar -keybind.toggle_menus.name = Toggle menus -keybind.chat_history_prev.name = Chat history prev -keybind.chat_history_next.name = Chat history next +setting.mutemusic.name = Diamkan Musik +setting.sfxvol.name = Volume SFX +setting.mutesound.name = Diamkan Suara +setting.crashreport.name = Laporkan Masalah +setting.chatopacity.name = Jelas-Beningnya Chat +setting.playerchat.name = Tunjukkan Chat dalam Permainan +keybind.title = Rebind Kunci +category.general.name = Umum +category.view.name = Melihat +category.multiplayer.name = Bermain Bersama +command.attack = Serang +command.retreat = Mundur +command.patrol = Patroli +keybind.gridMode.name = Pilih Blok +keybind.gridModeShift.name = Pilih Kategori +keybind.press = Tekan kunci... +keybind.press.axis = Tekan sumbu atau kunci... +keybind.screenshot.name = Tangkapan Layar Peta +keybind.move_x.name = Pindah x +keybind.move_y.name = Pindah y +keybind.select.name = Pilih/Tembak +keybind.diagonal_placement.name = Penaruhan Diagonal +keybind.pick.name = Memilih Blok +keybind.break_block.name = Menghancurkan Blok +keybind.deselect.name = Batal Memilih +keybind.shoot.name = Menembak +keybind.zoom_hold.name = Tahan Mode Zoom +keybind.zoom.name = Zoom +keybind.menu.name = Menu +keybind.pause.name = Jeda +keybind.minimap.name = Peta Kecil +keybind.dash.name = Terbang +keybind.chat.name = Chat +keybind.player_list.name = Daftar pemain +keybind.console.name = Console +keybind.rotate.name = Putar +keybind.toggle_menus.name = Muncul Tidaknya menu +keybind.chat_history_prev.name = Sejarah Chat sebelum +keybind.chat_history_next.name = Sejarah Chat sesudah keybind.chat_scroll.name = Chat scroll -keybind.drop_unit.name = drop unit -keybind.zoom_minimap.name = Zoom minimap -mode.help.title = Description of modes -mode.survival.name = Survival -mode.survival.description = The normal mode. Limited resources and automatic incoming waves. -mode.sandbox.name = sandbox -mode.sandbox.description = infinite resources and no timer for waves. +keybind.drop_unit.name = Jatuhkan Unit +keybind.zoom_minimap.name = Zoom peta kecil +mode.help.title = Deskripsi mode +mode.survival.name = Bertahan Hidup +mode.survival.description = Mode normal. Sumber Daya terbatas dan gelombang otomatis. +mode.sandbox.name = Mode Sandbox +mode.sandbox.description = Sumber Daya tak terbatas dan tidak ada gelombang otomatis. mode.pvp.name = PvP -mode.pvp.description = fight against other players locally. -mode.attack.name = Attack -mode.attack.description = No waves, with the goal to destroy the enemy base. -mode.custom = Custom Rules -rules.infiniteresources = Infinite Resources -rules.wavetimer = Wave Timer -rules.waves = Waves -rules.enemyCheat = Infinite AI Resources -rules.unitdrops = Unit Drops -rules.unitbuildspeedmultiplier = Unit Creation Speed Multiplier -rules.unithealthmultiplier = Unit Health Multiplier -rules.playerhealthmultiplier = Player Health Multiplier -rules.playerdamagemultiplier = Player Damage Multiplier -rules.unitdamagemultiplier = Unit Damage Multiplier -rules.enemycorebuildradius = Enemy Core No-Build Radius:[LIGHT_GRAY] (tiles) -rules.respawntime = Respawn Time:[LIGHT_GRAY] (sec) -rules.wavespacing = Wave Spacing:[LIGHT_GRAY] (sec) -rules.buildcostmultiplier = Build Cost Multiplier -rules.buildspeedmultiplier = Build Speed Multiplier -rules.waitForWaveToEnd = Waves wait for enemies -rules.dropzoneradius = Drop Zone Radius:[LIGHT_GRAY] (tiles) -rules.respawns = Max respawns per wave -rules.limitedRespawns = Limit Respawns -rules.title.waves = Waves -rules.title.respawns = Respawns -rules.title.resourcesbuilding = Resources & Building -rules.title.player = Players -rules.title.enemy = Enemies -rules.title.unit = Units -content.item.name = Items -content.liquid.name = Liquids -content.unit.name = Units -content.block.name = Blocks -content.mech.name = Mechs -item.copper.name = Copper -item.copper.description = A useful structure material. Used extensively in all types of blocks. -item.lead.name = Lead -item.lead.description = A basic starter material. Used extensively in electronics and liquid transportation blocks. -item.coal.name = batu bara -item.coal.description = A common and readily available fuel. -item.graphite.name = Graphite -item.titanium.name = titanium -item.titanium.description = A rare super-light metal used extensively in liquid transportation, drills and aircraft. -item.thorium.name = thorium -item.thorium.description = A dense, radioactive metal used as structural support and nuclear fuel. -item.silicon.name = Silicon -item.silicon.description = An extremely useful semiconductor, with applications in solar panels and many complex electronics. +mode.pvp.description = Melawan Pemain lain. Membutuhkan setidaknya 2 inti berbeda warna didalam peta untuk main. +mode.attack.name = Penyerangan +mode.attack.description = Menghancurkan base musuh. Tidak ada gelombang. Membutuhkan inti merah di dalam peta untuk main. +mode.custom = Pengaturan Modifikasi +rules.infiniteresources = Sumber Daya Tak Terbatas +rules.wavetimer = Pengaturan Waktu Gelombang +rules.waves = Gelombang +rules.enemyCheat = Sumber Daya A.I Musuh (Tim Merah) Tak Terbatas +rules.unitdrops = Munculnya Unit +rules.unitbuildspeedmultiplier = Multiplikasi Kecepatan Munculnya Unit +rules.unithealthmultiplier = Multiplikasi Darah Unit +rules.playerhealthmultiplier = Multiplikasi Darah Pemain +rules.playerdamagemultiplier = Multiplikasi Kekuatan Pemain +rules.unitdamagemultiplier = Multiplikasi Kekuatan Unit +rules.enemycorebuildradius = Dilarang-Membangun Radius Inti Musuh :[LIGHT_GRAY] (blok) +rules.respawntime = Waktu Respawn:[LIGHT_GRAY] (detik) +rules.wavespacing = Jarak Gelombang:[LIGHT_GRAY] (detik) +rules.buildcostmultiplier = Multiplikasi Harga Bangunan +rules.buildspeedmultiplier = Multiplikasi Waktu Pembuatan Bangunan +rules.waitForWaveToEnd = Gelombang menunggu musuh +rules.dropzoneradius = Radius Titik Muncul:[LIGHT_GRAY] (Blok) +rules.respawns = Maks respawn per gelombang +rules.limitedRespawns = Batas Respawn +rules.title.waves = Gelombang +rules.title.respawns = Respawn +rules.title.resourcesbuilding = Sumber Daya & Bangunan +rules.title.player = Pemain +rules.title.enemy = Musush +rules.title.unit = Unit +content.item.name = Item +content.liquid.name = Zat Cair +content.unit.name = Unit +content.block.name = Blok +content.mech.name = Robot +item.copper.name = Tembaga +item.copper.description = Bahan struktur yang berguna. Digunakan di semua tipe blok. +item.lead.name = Timah +item.lead.description = Bahan dasar di awal permainan. Digunakan di elektronik dan blok transportasi zat cair. +item.coal.name = Batu Bara +item.coal.description = Bahan Bakar umum. +item.graphite.name = Grafit +item.titanium.name = Titanium +item.titanium.description = Logam langka yang super-ringan digunakan di transportasi zat cair, bor dan pesawat terbang. +item.thorium.name = Thorium +item.thorium.description = Logam yang padat dan radioaktif, sebagai bantuan struktur ban bahan bakar nuklir. +item.silicon.name = Silikon +item.silicon.description = Semikonduktor yang sangat berguna, penerapan di panel surya dan banyak benda electronik. item.plastanium.name = Plastanium -item.plastanium.description = A light, ductile material used in advanced aircraft and fragmentation ammunition. -item.phase-fabric.name = Phase Fabric -item.phase-fabric.description = A near-weightless substance used in advanced electronics and self-repairing technology. -item.surge-alloy.name = Surge Alloy -item.surge-alloy.description = An advanced alloy with unique electrical properties. -item.spore-pod.name = Spore Pod -item.spore-pod.description = Used for conversion into oil, explosives and fuel. -item.sand.name = pasir -item.sand.description = A common material that is used extensively in smelting, both in alloying and as a flux. -item.blast-compound.name = Blast Compound -item.blast-compound.description = A volatile compound used in bombs and explosives. While it can burned as fuel, this is not advised. +item.plastanium.description = Bahan yang ringan dan elastis, digunakan di pesawat terbang canggih dan amunisi kepingan. +item.phase-fabric.name = Kain Phase +item.phase-fabric.description = Zat yang hampir tidak ada bobot ini digunakan di elektronik canggih dan teknologi reparasi. +item.surge-alloy.name = Paduan Surge +item.surge-alloy.description = Paduan canggih dengan properti listrik yang unik. +item.spore-pod.name = Spora Polong +item.spore-pod.description = Digunakan untuk produksi oli, bahan peledak dan bahan bakar. +item.sand.name = Pasir +item.sand.description = Bahan umum yang digunakan di berbagai peleburan +item.blast-compound.name = Senyawa Peledak +item.blast-compound.description = Senyawa yang digunakan di bom dan peledak lainnya. Bisa dipakai untuk bahan bakar, tetapi tidak disarankan. item.pyratite.name = Pyratite -item.pyratite.description = An extremely flammable substance used in incendiary weapons. -item.metaglass.name = Metaglass -item.metaglass.description = A super-tough glass compound. Extensively used for liquid distribution and storage. -item.scrap.name = Scrap -item.scrap.description = Leftover remnants of old structures and units. Contains trace amounts of many different metals. -liquid.water.name = air -liquid.slag.name = Slag -liquid.oil.name = minyak +item.pyratite.description = Zat yang mudah dibakar ini digunakan di senjata pembakar. +item.metaglass.name = Kaca Meta +item.metaglass.description = Kaca yang super-kuat. Digunakan untuk distribusi zar cair dan penyimpanan. +item.scrap.name = Kepingan +item.scrap.description = Peninggalan bangunan dan unit tua. mengandung beberapa zat logam. +liquid.water.name = Air +liquid.slag.name = Ampas +liquid.oil.name = Oli 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.name = Alfa +mech.alpha-mech.weapon = Repeater Berat +mech.alpha-mech.ability = Regenerasi +mech.alpha-mech.description = Robot standar. Mempunyai kecepatan dan kekuatan yang sedang. mech.delta-mech.name = Delta -mech.delta-mech.weapon = Arc Generator -mech.delta-mech.ability = Discharge -mech.delta-mech.description = A fast, lightly-armored mech made for hit-and-run attacks. Does little damage against structures, but can kill large groups of enemy units very quickly with its arc lightning weapons. -mech.tau-mech.name = Tau -mech.tau-mech.weapon = Restruct Laser -mech.tau-mech.ability = Repair Burst -mech.tau-mech.description = The support mech. Heals allied blocks by shooting at them. Can extinguish fires and heal allies in a radius with its repair ability. +mech.delta-mech.weapon = Generator Arca +mech.delta-mech.ability = Kekuatan Listrik +mech.delta-mech.description = Robot baja yang cepat dan ringan, dibuat untuk serangan tabrak-lari. Tidak kuat melawan bangunan, tapi bisa membunuh grup musuh dengan cepat memakai senjata petirnya. +mech.tau-mech.name = Tao +mech.tau-mech.weapon = Laser Pemulih +mech.tau-mech.ability = Perbaikan Konstan +mech.tau-mech.description = Robot support. Menyembuhkan blok teman dengan menembaknya. Bisa menyembuhkan teman di sekitarnya. mech.omega-mech.name = Omega -mech.omega-mech.weapon = Swarm Missiles -mech.omega-mech.ability = Armored Configuration -mech.omega-mech.description = A bulky and well-armored mech, made for front-line assaults. Its armor ability can block up to 90% of incoming damage. +mech.omega-mech.weapon = Misil Berkelompok +mech.omega-mech.ability = Konfigurasi Berbaja +mech.omega-mech.description = Robot yang besar dan berbaja, Dibuat untuk serangan baris depan. Kekuatan bajanya bisa memantulkan 90% pukulan lawan. mech.dart-ship.name = Dart -mech.dart-ship.weapon = Repeater -mech.dart-ship.description = The standard ship. Reasonably fast and light, but has little offensive capability and low mining speed. +mech.dart-ship.weapon = Bertubi-Tubi +mech.dart-ship.description = Pesawat starndar. cpeat dan ringan, tetapi mempunyai sedikit tenaga dan penambang yang pelan. mech.javelin-ship.name = Javelin -mech.javelin-ship.description = A hit-and-run strike ship. While initially slow, it can accelerate to great speeds and fly by enemy outposts, dealing large amounts of damage with its lightning ability and missiles. -mech.javelin-ship.weapon = Burst Missiles -mech.javelin-ship.ability = Discharge Booster +mech.javelin-ship.description = Pesawat tabrak-lari. Walaupun pelan, bisa dipercepat sekencang kilat, memiliki kekuatan yang besar dengan kemampuan listrik dan misilnya. +mech.javelin-ship.weapon = Misil Bertubi-tubi +mech.javelin-ship.ability = Booster Listrik mech.trident-ship.name = Trident -mech.trident-ship.description = A heavy bomber. Reasonably well armored. -mech.trident-ship.weapon = Bomb Bay +mech.trident-ship.description = Pengebom kelas berat. Berbaja kuat. +mech.trident-ship.weapon = Lahan Bom mech.glaive-ship.name = Glaive -mech.glaive-ship.description = A large, well-armored gunship. Equipped with an incendiary repeater. Good acceleration and maximum speed. -mech.glaive-ship.weapon = Flame Repeater -item.explosiveness = [LIGHT_GRAY]Explosiveness: {0} -item.flammability = [LIGHT_GRAY]Flammability: {0} -item.radioactivity = [LIGHT_GRAY]Radioactivity: {0} -unit.health = [LIGHT_GRAY]Health: {0} -unit.speed = [LIGHT_GRAY]Speed: {0} -mech.weapon = [LIGHT_GRAY]Weapon: {0} -mech.health = [LIGHT_GRAY]Health: {0} -mech.itemcapacity = [LIGHT_GRAY]Item Capacity: {0} -mech.minespeed = [LIGHT_GRAY]Mining Speed: {0} -mech.minepower = [LIGHT_GRAY]Mining Power: {0} -mech.ability = [LIGHT_GRAY]Ability: {0} -mech.buildspeed = [LIGHT_GRAY]Building Speed: {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.saltrocks.name = Salt Rocks -block.pebbles.name = Pebbles -block.tendrils.name = Tendrils -block.sandrocks.name = Sand Rocks -block.spore-pine.name = Spore Pine -block.sporerocks.name = Spore Rocks -block.rock.name = Rock -block.snowrock.name = Snow Rock -block.shale.name = Shale -block.shale-boulder.name = Shale Boulder -block.moss.name = Moss -block.shrubs.name = Shrubs -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 +mech.glaive-ship.description = Pesawat tempur yang besar nan kuat. Memiliki senjata pembakar. Kecepatan yang bagus. +mech.glaive-ship.weapon = Repeater Api +item.explosiveness = [LIGHT_GRAY]Tingkat Keledakan: {0}% +item.flammability = [LIGHT_GRAY]Tingkat Kebakaran: {0}% +item.radioactivity = [LIGHT_GRAY]Tingkat Radioaktif: {0}% +unit.health = [LIGHT_GRAY]Darah: {0} +unit.speed = [LIGHT_GRAY]Kecepatan: {0} +mech.weapon = [LIGHT_GRAY]Senjata: {0} +mech.health = [LIGHT_GRAY]Darah: {0} +mech.itemcapacity = [LIGHT_GRAY]Kapasitas Item: {0} +mech.minespeed = [LIGHT_GRAY]Kecepatan Menambang: {0}% +mech.minepower = [LIGHT_GRAY]Kekuatan Menambang: {0} +mech.ability = [LIGHT_GRAY]Kemampuan: {0} +mech.buildspeed = [LIGHT_GRAY]Kecepatan Membangun: {0}% +liquid.heatcapacity = [LIGHT_GRAY]Kapasitas Panas: {0} +liquid.viscosity = [LIGHT_GRAY]Kelekatan: {0} +liquid.temperature = [LIGHT_GRAY]Suhu: {0} +block.grass.name = Rumput +block.salt.name = Garam +block.saltrocks.name = Batu Garam +block.pebbles.name = Kerikil +block.tendrils.name = Sulur +block.sandrocks.name = Batu Pasir +block.spore-pine.name = Cemara Spora +block.sporerocks.name = Batu Spora +block.rock.name = Batu +block.snowrock.name = Batu Salju +block.shale.name = Serpihan +block.shale-boulder.name = Serpihan Batu Besar +block.moss.name = Lumut +block.shrubs.name = Semak-Semak +block.spore-moss.name = Lumut Spora +block.shalerocks.name = Batu Serpihan +block.scrap-wall.name = Dinding Kepingan +block.scrap-wall-large.name = Dinding Kepingan Besar 1 +block.scrap-wall-huge.name = Dinding Kepingan Besar 2 +block.scrap-wall-gigantic.name = Dinding Kepingan Besar 3 +block.thruster.name = Pendorong 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](Constructing) -block.spawn.name = Enemy Spawn -block.core-shard.name = Core: Shard -block.core-foundation.name = Core: Foundation -block.core-nucleus.name = Core: Nucleus -block.deepwater.name = deepwater -block.water.name = water -block.tainted-water.name = Tainted Water -block.darksand-tainted-water.name = Dark Sand Tainted Water -block.tar.name = Tar -block.stone.name = stone -block.sand.name = sand -block.darksand.name = Dark Sand -block.ice.name = ice -block.snow.name = snow -block.craters.name = Craters -block.sand-water.name = Sand water -block.darksand-water.name = Dark Sand Water -block.char.name = Char -block.holostone.name = Holo stone -block.ice-snow.name = Ice Snow -block.rocks.name = Rocks -block.icerocks.name = Ice rocks -block.snowrocks.name = Snow Rocks -block.dunerocks.name = Dune Rocks -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.metal-floor.name = Metal Floor -block.metal-floor-2.name = Metal Floor 2 -block.metal-floor-3.name = Metal Floor 3 -block.metal-floor-5.name = Metal Floor 5 -block.metal-floor-damaged.name = Metal Floor Damaged -block.dark-panel-1.name = Dark Panel 1 -block.dark-panel-2.name = Dark Panel 2 -block.dark-panel-3.name = Dark Panel 3 -block.dark-panel-4.name = Dark Panel 4 -block.dark-panel-5.name = Dark Panel 5 -block.dark-panel-6.name = Dark Panel 6 -block.dark-metal.name = Dark Metal -block.ignarock.name = Igna Rock -block.hotrock.name = Hot Rock -block.magmarock.name = Magma Rock -block.cliffs.name = Cliffs -block.copper-wall.name = Copper Wall -block.copper-wall-large.name = Large Copper Wall -block.titanium-wall.name = Titanium Wall -block.titanium-wall-large.name = Large Titanium Wall -block.phase-wall.name = Phase Wall -block.phase-wall-large.name = Large Phase Wall -block.thorium-wall.name = Thorium Wall -block.thorium-wall-large.name = Large Thorium Wall -block.door.name = pintu -block.door-large.name = pintu besar +block.kiln.description = Membakar pasir dan timah menjadi kaca meta. Membutuhkan Listrik. +block.graphite-press.name = Pencetak Grafit +block.multi-press.name = Multi-Cetak +block.constructing = {0} [LIGHT_GRAY](Konstruksi) +block.spawn.name = Muncul Musuh +block.core-shard.name = Inti: Bagian +block.core-foundation.name = Inti: Pondasi +block.core-nucleus.name = Inti: Nucleus +block.deepwater.name = Air Dalam +block.water.name = Air +block.tainted-water.name = Air Ternoda +block.darksand-tainted-water.name = Air Ternodai Pasir Hitam +block.tar.name = Ter +block.stone.name = Batu +block.sand.name = Pasir +block.darksand.name = Pasir Hitam +block.ice.name = Es +block.snow.name = Salju +block.craters.name = Kawah +block.sand-water.name = Air pasir +block.darksand-water.name = Air pasir hitam +block.char.name = Bara +block.holostone.name = Batu holo +block.ice-snow.name = Salju Es +block.rocks.name = Batu +block.icerocks.name = Batu Es +block.snowrocks.name = Batu Salju +block.dunerocks.name = Bukit Pasir +block.pine.name = Cemara +block.white-tree-dead.name = Pohon Putih Mati +block.white-tree.name = Pohon Putih +block.spore-cluster.name = Kumpulan Spora +block.metal-floor.name = Lantai Besi 1 +block.metal-floor-2.name = Lantai Besi 2 +block.metal-floor-3.name = Lantai Besi 3 +block.metal-floor-5.name = Lantai Besi 4 +block.metal-floor-damaged.name = Lantai Besi Rusak +block.dark-panel-1.name = Panel Gelap 1 +block.dark-panel-2.name = Panel Gelap 2 +block.dark-panel-3.name = Panel Gelap 3 +block.dark-panel-4.name = Panel Gelap 4 +block.dark-panel-5.name = Panel Gelap 5 +block.dark-panel-6.name = Panel Gelap 6 +block.dark-metal.name = Besi Gelap +block.ignarock.name = Batu Igna +block.hotrock.name = Batu Panas +block.magmarock.name = Batu Lahar +block.cliffs.name = Tebing +block.copper-wall.name = Dinding Tembaga +block.copper-wall-large.name = Dinding Tembaga Besar +block.titanium-wall.name = Dinding Titanium +block.titanium-wall-large.name = Dinding Titanium Besar +block.phase-wall.name = Dinding Phase +block.phase-wall-large.name = Dinding Phase Besar +block.thorium-wall.name = Dinding Thorium +block.thorium-wall-large.name = Dinding Thorium Besar +block.door.name = Pintu +block.door-large.name = Pintu Besar block.duo.name = Duo -block.scorch.name = Scorch -block.scatter.name = Scatter +block.scorch.name = Penghangus +block.scatter.name = Penabur block.hail.name = Hail block.lancer.name = Lancer -block.conveyor.name = konveyor -block.titanium-conveyor.name = Titanium Conveyor -block.junction.name = persimpangan jalan -block.router.name = router +block.conveyor.name = Pengantar +block.titanium-conveyor.name = Pengantar Berbahan Titanium +block.junction.name = Simpangan +block.router.name = Pengarah block.distributor.name = Distributor -block.sorter.name = penyortir -block.sorter.description = Sorts items. If an item matches the selection, it is allowed to pass. Otherwise, the item is outputted to the left and right. -block.overflow-gate.name = Overflow Gate -block.overflow-gate.description = A combination splitter and router that only outputs to the left and right if the front path is blocked. -block.silicon-smelter.name = Silicon Smelter -block.phase-weaver.name = Phase Weaver -block.pulverizer.name = Pulverizer -block.cryofluidmixer.name = Cryofluid Mixer -block.melter.name = Melter -block.incinerator.name = Incinerator -block.spore-press.name = Spore Press -block.separator.name = Separator -block.coal-centrifuge.name = Coal Centrifuge -block.power-node.name = Power Node -block.power-node-large.name = Large Power Node -block.surge-tower.name = Surge Tower -block.battery.name = Battery -block.battery-large.name = Large Battery -block.combustion-generator.name = Combustion Generator -block.turbine-generator.name = Turbine Generator -block.differential-generator.name = Differential Generator -block.impact-reactor.name = Impact Reactor -block.mechanical-drill.name = Mechanical Drill -block.pneumatic-drill.name = Pneumatic Drill -block.laser-drill.name = Laser Drill -block.water-extractor.name = Water Extractor -block.cultivator.name = Cultivator -block.dart-mech-pad.name = Dart Mech Pad -block.delta-mech-pad.name = Delta Mech Pad -block.javelin-ship-pad.name = Javelin Ship Pad -block.trident-ship-pad.name = Trident Ship Pad -block.glaive-ship-pad.name = Glaive Ship Pad -block.omega-mech-pad.name = Omega Mech Pad -block.tau-mech-pad.name = Tau Mech Pad -block.conduit.name = saluran -block.mechanical-pump.name = Mechanical Pump -block.item-source.name = Item Source -block.item-void.name = Item Void -block.liquid-source.name = Liquid Source -block.power-void.name = Power Void -block.power-source.name = Power Infinite -block.unloader.name = Unloader +block.sorter.name = Penyortir +block.sorter.description = Memilah Item. Jika item cocok dengan seleksi, itemnya diperbolehkan lewat. Jika Tidak, item akan dikeluarkan dari kiri dan/atau kanan. +block.overflow-gate.name = Gerbang Meluap +block.overflow-gate.description = Kombinasi antara pemisah dan penyortir yang hanya mengeluarkan item ke kiri dan/atau ke kanan jika bagian depan tertutup. +block.silicon-smelter.name = Pelebur Silikon +block.phase-weaver.name = Pengrajut Phase +block.pulverizer.name = Penyemprot +block.cryofluidmixer.name = Mixer Cryofluid +block.melter.name = Pencair +block.incinerator.name = Penghangus +block.spore-press.name = Penekan Spora +block.separator.name = Pemisah +block.coal-centrifuge.name = Sentrifugal Batu Bara +block.power-node.name = Tiang Listrik +block.power-node-large.name = Tiang Listrik Besar +block.surge-tower.name = Tiang Surge +block.battery.name = Baterai +block.battery-large.name = Baterai Besar +block.combustion-generator.name = Generator Pembakar +block.turbine-generator.name = Generator Turbin +block.differential-generator.name = Generator Pembeda +block.impact-reactor.name = Reaktor Benturan +block.mechanical-drill.name = Bor Mekanik +block.pneumatic-drill.name = Bor Pneumatik +block.laser-drill.name = Bor Laser +block.water-extractor.name = Pengekstrak Air +block.cultivator.name = Pembudidaya +block.dart-mech-pad.name = Alfa Robot Pad +block.delta-mech-pad.name = Delta Robot Pad +block.javelin-ship-pad.name = Pesawat Javelin Pad +block.trident-ship-pad.name = Pesawat Trident Pad +block.glaive-ship-pad.name = Pesawat Glaive Pad +block.omega-mech-pad.name = Omega Robot Pad +block.tau-mech-pad.name = Tao Robot Pad +block.conduit.name = Saluran +block.mechanical-pump.name = Pompa Mekanik +block.item-source.name = Sumber Item +block.item-void.name = Penghilang Item +block.liquid-source.name = Sumber Zat Cair +block.power-void.name = Penghilang Listrik +block.power-source.name = Listrik Tak Terbatas +block.unloader.name = Pembongkar Muatan block.vault.name = Vault block.wave.name = Wave -block.swarmer.name = Swarmer +block.swarmer.name = Pengurung block.salvo.name = Salvo -block.ripple.name = Ripple -block.phase-conveyor.name = Phase Conveyor -block.bridge-conveyor.name = Bridge Conveyor -block.plastanium-compressor.name = Plastanium Compressor -block.pyratite-mixer.name = Pyratite Mixer -block.blast-mixer.name = Blast Mixer -block.solar-panel.name = Solar Panel -block.solar-panel-large.name = Large Solar Panel -block.oil-extractor.name = Oil Extractor -block.spirit-factory.name = Spirit Drone Factory -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 -block.repair-point.name = Repair Point -block.pulse-conduit.name = Pulse Conduit -block.phase-conduit.name = Phase Conduit -block.liquid-router.name = Liquid Router -block.liquid-tank.name = Liquid Tank -block.liquid-junction.name = Liquid Junction -block.bridge-conduit.name = Bridge Conduit -block.rotary-pump.name = Rotary Pump -block.thorium-reactor.name = Thorium Reactor -block.mass-driver.name = Mass Driver -block.blast-drill.name = Blast Drill -block.thermal-pump.name = Thermal Pump -block.thermal-generator.name = Thermal Generator -block.alloy-smelter.name = Alloy Smtler -block.mender.name = Mender -block.mend-projector.name = Mend Projector -block.surge-wall.name = Surge Wall -block.surge-wall-large.name = Large Surge Wall -block.cyclone.name = Cyclone -block.fuse.name = Fuse -block.shock-mine.name = Shock Mine -block.overdrive-projector.name = Overdrive Projector -block.force-projector.name = Force Projector -block.arc.name = Arc -block.rtg-generator.name = RTG Generator -block.spectre.name = Spectre -block.meltdown.name = Meltdown -block.container.name = Container -block.launch-pad.name = Launch Pad -block.launch-pad.description = Launches batches of items without any need for a core launch. Unfinished. -block.launch-pad-large.name = Large Launch Pad -team.blue.name = blue -team.red.name = red -team.orange.name = orange -team.none.name = gray -team.green.name = green -team.purple.name = purple -unit.spirit.name = Spirit Drone -unit.spirit.description = The starter drone unit. Spawns in the core by default. Automatically mines ores, collects items and repairs blocks. -unit.phantom.name = Phantom Drone -unit.phantom.description = An advanced drone unit. Automatically mines ores, collects items and repairs blocks. Significantly more effective than a drone. +block.ripple.name = Periak +block.phase-conveyor.name = Pengantar Berbahan Phase +block.bridge-conveyor.name = Jembatan Pengantar +block.plastanium-compressor.name = Pembentuk Plastanium +block.pyratite-mixer.name = Mixer Pyratite +block.blast-mixer.name = Mixer Peledak +block.solar-panel.name = Panel Surya +block.solar-panel-large.name = Panel Surya Besar +block.oil-extractor.name = Pegekstrak Oli +block.spirit-factory.name = Pabrik Drone Spirit +block.phantom-factory.name = Pabrik Drone Phantom +block.wraith-factory.name = Pabrik Penyerang Wraith +block.ghoul-factory.name = Pabrik Pengebom Ghoul +block.dagger-factory.name = Pabrik Robot Dagger +block.crawler-factory.name = Pabrik Robot Crawler +block.titan-factory.name = Pabrik Robot Titan +block.fortress-factory.name = Pabrik Robot Fortress +block.revenant-factory.name = Pabrik Penyerang Revenant +block.repair-point.name = Titik Pulih +block.pulse-conduit.name = Selang Denyut +block.phase-conduit.name = Selang Berbahan Phase +block.liquid-router.name = Penyortir Zat Cair +block.liquid-tank.name = Tank Zat Cair +block.liquid-junction.name = Simpangan Zat Cair +block.bridge-conduit.name = Jembatan Saluran +block.rotary-pump.name = Pompa Putar +block.thorium-reactor.name = Reaktor Thorium +block.mass-driver.name = Driver Massal +block.blast-drill.name = Bor Peledak +block.thermal-pump.name = Pompa Termis +block.thermal-generator.name = Generator Termis +block.alloy-smelter.name = Pelebur Paduan +block.mender.name = Reparator +block.mend-projector.name = Proyeksi Reparator +block.surge-wall.name = Dinding Surge +block.surge-wall-large.name = Dinding Surge Besar +block.cyclone.name = Topan +block.fuse.name = Padu +block.shock-mine.name = Ranjau Listrik +block.overdrive-projector.name = Proyeksi Pencepat +block.force-projector.name = Proyeksi Medan Gaya +block.arc.name = Arca +block.rtg-generator.name = Generator RTG +block.spectre.name = Iblis +block.meltdown.name = Pelampiasan +block.container.name = Kontainer +block.launch-pad.name = Pad Peluncur +block.launch-pad.description = Meluncurkan beberapa item tanpa meninggalkan base. +block.launch-pad-large.name = Pad Peluncur Besar +team.blue.name = biru +team.red.name = merah +team.orange.name = jingga +team.none.name = abu-abu +team.green.name = hijau +team.purple.name = ungu +unit.spirit.name = Drone Spirit +unit.spirit.description = unit pemulaan. muncul di inti secara standar. Menambang sumber daya dan memperbaiki blok. +unit.phantom.name = Drone Phantom +unit.phantom.description = unit canggih. Menambang sumber daya dan memperbaiki blok. Lebih efektif dari drone spirit. unit.dagger.name = Dagger -unit.dagger.description = A basic ground unit. Useful in swarms. +unit.dagger.description = Unit darat dasar. Berguna di kelompok. unit.crawler.name = Crawler unit.titan.name = Titan -unit.titan.description = An advanced armored ground unit. Uses carbide as ammo. Attacks both ground and air targets. -unit.ghoul.name = Ghoul Bomber -unit.ghoul.description = A heavy carpet bomber. Uses blast compound or pyratite as ammo. -unit.wraith.name = Wraith Fighter -unit.wraith.description = A fast, hit-and-run interceptor unit. +unit.titan.description = Unit darat berbaja yang canggih ini menyerang target darat dan udara. +unit.ghoul.name = Pengebom Ghoul +unit.ghoul.description = Pengebom kelas berat. +unit.wraith.name = Penyerang Wraith +unit.wraith.description = Unit tabrak-lari yang cepat. unit.fortress.name = Fortress -unit.fortress.description = A heavy artillery ground unit. +unit.fortress.description = Unit meriam darat kelas berat. unit.revenant.name = Revenant -unit.eruptor.name = Eruptor -unit.chaos-array.name = Chaos Array -unit.eradicator.name = Eradicator +unit.eruptor.name = Peletus +unit.chaos-array.name = Satuan Kekacauan +unit.eradicator.name = Pemusnah unit.lich.name = Lich -unit.reaper.name = Reaper -tutorial.begin = Your mission here is to eradicate the[LIGHT_GRAY] enemy[].\n\nBegin by[accent] mining copper[]. Tap a copper ore vein near your core to do this. -tutorial.drill = Mining manually is inefficient.\n[accent]Drills []can mine automatically.\nPlace one on a copper vein. -tutorial.conveyor = [accent]Conveyors[] are used to transport items to the core.\nMake a line of conveyors from the drill to the core. -tutorial.morecopper = More copper is required.\n\nEither mine it manually, or place more drills. -tutorial.turret = Defensive structures must be built to repel the[LIGHT_GRAY] enemy[].\nBuild a duo turret near your base. -tutorial.drillturret = Duo turrets require[accent] copper ammo []to shoot.\nPlace a drill next to the turret to supply it with mined copper. -tutorial.waves = The[LIGHT_GRAY] enemy[] approaches.\n\nDefend your core for 2 waves. Build more turrets. -tutorial.lead = More ores are available. Explore and mine[accent] lead[].\n\nDrag from your unit to the core to transfer resources. -tutorial.smelter = Copper and lead are weak metals.\nSuperior[accent] Dense Alloy[] can be created in a smelter.\n\nBuild one. -tutorial.densealloy = The smelter will now produce alloy.\nGet some.\nImprove the production if necessary. -tutorial.siliconsmelter = The core will now create a[accent] spirit drone[] for mining and repairing blocks.\n\nFactories for other units can be created with [accent] silicon.\nMake a silicon smelter. -tutorial.silicondrill = Silicon requires[accent] coal[] and[accent] sand[].\nStart by making drills. -tutorial.generator = This technology requires power.\nCreate a[accent] combustion generator[] for it. -tutorial.generatordrill = Combustion generators need fuel.\nFuel it with coal from a drill. -tutorial.node = Power requires transport.\nCreate a[accent] power node[] next to your combustion generator to transfer its power. -tutorial.nodelink = Power can be transferred through contacting power blocks and generators, or by linked power nodes.\n\nLink power by tapping the node and selecting the generator and silicon smelter. -tutorial.silicon = Silicon is being produced. Get some.\n\nImproving the production system is advised. -tutorial.daggerfactory = Construct a[accent] dagger mech factory.[]\n\nThis will be used to create attack mechs. -tutorial.router = Factories need resources to function.\nCreate a router to split conveyor resources. -tutorial.dagger = Link power nodes to the factory.\nOnce requirements are met, a mech will be created.\n\nCreate more drills, generators and conveyors as necessary. -tutorial.battle = The[LIGHT_GRAY] enemy[] has revealed their core.\nDestroy it with your unit and dagger mechs. -block.copper-wall.description = A cheap defensive block.\nUseful for protecting the core and turrets in the first few waves. -block.copper-wall-large.description = A cheap defensive block.\nUseful for protecting the core and turrets in the first few waves.\nSpans multiple tiles. -block.thorium-wall.description = A strong defensive block.\nGood protection from enemies. -block.thorium-wall-large.description = A strong defensive block.\nGood protection from enemies.\nSpans multiple tiles. -block.phase-wall.description = Not as strong as a thorium wall but will deflect bullets unless they are too powerful. -block.phase-wall-large.description = Not as strong as a thorium wall but will deflect bullets unless they are too powerful.\nSpans multiple tiles. -block.surge-wall.description = The strongest defensive block.\nHas a small chance of triggering lightning towards the attacker. -block.surge-wall-large.description = The strongest defensive block.\nHas a small chance of triggering lightning towards the attacker.\nSpans multiple tiles. -block.door.description = A small door that can be opened and closed by tapping on it.\nIf opened, enemies can shoot and move through. -block.door-large.description = A large door that can be opened and closed by tapping on it.\nIf opened, enemies can shoot and move through.\nSpans multiple tiles. -block.mend-projector.description = Periodically heals buildings 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.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. -block.wave.description = A medium-sized rapid-fire turret which shoots liquid bubbles. -block.salvo.description = A medium-sized turret which fires shots in salvos. -block.swarmer.description = A medium-sized turret which shoots burst missiles. -block.ripple.description = A large artillery turret which fires several shots simultaneously. -block.cyclone.description = A large rapid fire turret. -block.fuse.description = A large turret which shoots powerful short-range beams. -block.spectre.description = A large turret which shoots two powerful bullets at once. -block.meltdown.description = A large turret which shoots powerful long-range beams. -block.conveyor.description = Basic item transport block. Moved items forward and automatically deposits them into turrets or crafters. Rotatable. -block.titanium-conveyor.description = Advanced item transport block. Moves items faster than standard conveyors. -block.phase-conveyor.description = Advanced item transport block. Uses power to teleport items to a connected phase conveyor over several tiles. -block.junction.description = Acts as a bridge for two crossing conveyor belts. Useful in situations with two different conveyors carrying different materials to different locations. -block.mass-driver.description = Ultimate item transport block. Collects several items and then shoots them to another mass driver over a long range. -block.silicon-smelter.description = Reduces sand with highly pure coke in order to produce silicon. -block.plastanium-compressor.description = Produces plastanium from oil and titanium. -block.phase-weaver.description = Produces phase fabric from radioactive thorium and high amounts of sand. -block.alloy-smelter.description = Produces surge alloy from titanium, lead, silicon and copper. -block.pulverizer.description = Crushes stone into sand. Useful when there is a lack of natural sand. -block.pyratite-mixer.description = Mixes coal, lead and sand into highly flammable pyratite. -block.blast-mixer.description = Uses oil for transforming pyratite into the less flammable but more explosive blast compound. -block.cryofluidmixer.description = Combines water and titanium into cryofluid which is much more efficient for cooling. -block.melter.description = Heats up stone to very high temperatures to obtain lava. -block.incinerator.description = Gets rid of any excess item or liquid. -block.spore-press.description = Compresses spore pods into oil. -block.separator.description = Exposes stone to water pressure in order to obtain various minerals contained in the stone. -block.power-node.description = Transmits power to connected nodes. Up to four power sources, sinks or nodes can be connected. The node will receive power from or supply power to any adjacent blocks. -block.power-node-large.description = Has a larger radius than the power node and connects to up to six power sources, sinks or nodes. -block.battery.description = Stores power whenever there is an abundance and provides power whenever there is a shortage, as long as there is capacity left. -block.battery-large.description = Stores much more power than a regular battery. -block.combustion-generator.description = Generates power by burning oil or flammable materials. -block.turbine-generator.description = More efficient than a combustion generator, but requires additional water. -block.thermal-generator.description = Generates a large amount of power from lava. -block.solar-panel.description = Provides a small amount of power from the sun. -block.solar-panel-large.description = Provides much better power supply than a standard solar panel, but is also much more expensive to build. -block.thorium-reactor.description = Generates huge amounts of power from highly radioactive thorium. Requires constant cooling. Will explode violently if insufficient amounts of coolant are supplied. -block.rtg-generator.description = A radioisotope thermoelectric generator which does not require cooling but provides less power than a thorium reactor. -block.unloader.description = Unloads items from a container, vault or core onto a conveyor or directly into an adjacent block. The type of item to be unloaded can be changed by tapping on the unloader. -block.container.description = Stores a small amount of items. Use it for creating buffers when there is a non-constant demand of materials. An[LIGHT_GRAY] unloader[] can be used to retrieve items from the container. -block.vault.description = Stores a large amount of items. Use it for creating buffers when there is a non-constant demand of materials. An[LIGHT_GRAY] unloader[] can be used to retrieve items from the vault. -block.mechanical-drill.description = A cheap drill. When placed on appropriate tiles, outputs items at a slow pace indefinitely. -block.pneumatic-drill.description = An improved drill which is faster and able to process harder materials by making use of air pressure. -block.laser-drill.description = Allows drilling even faster through laser technology, but requires power. Additionally, radioactive thorium can be retrieved with this drill. -block.blast-drill.description = The ultimate drill. Requires large amounts of power. -block.water-extractor.description = Extracts water from the ground. Use it when there is no lake nearby. -block.cultivator.description = Cultivates the soil with water in order to obtain biomatter. -block.oil-extractor.description = Uses large amounts of power in order to extract oil from sand. Use it when there is no direct source of oil nearby. -block.trident-ship-pad.description = Leave your current vessel and change into a reasonably well armored heavy bomber.\nUse the pad by double tapping while standing on it. -block.javelin-ship-pad.description = Leave your current vessel and change into a strong and fast interceptor with lightning weapons.\nUse the pad by double tapping while standing on it. -block.glaive-ship-pad.description = Leave your current vessel and change into a large, well-armored gunship.\nUse the pad by double tapping while standing on it. -block.tau-mech-pad.description = Leave your current vessel and change into a support mech which can heal friendly buildings and units.\nUse the pad by double tapping while standing on it. -block.delta-mech-pad.description = Leave your current vessel and change into a fast, lightly-armored mech made for hit-and-run attacks.\nUse the pad by double tapping while standing on it. -block.omega-mech-pad.description = Leave your current vessel and change into a bulky and well-armored mech, made for front-line assaults.\nUse the pad by double tapping while standing on it. -block.spirit-factory.description = Produces light drones which mine ore and repair blocks. -block.phantom-factory.description = Produces advanced drone units which are significantly more effective than a spirit drone. -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 ground units. -block.repair-point.description = Continuously heals the closest damaged unit in its vicinity. -block.conduit.description = Basic liquid transport block. Works like a conveyor, but with liquids. Best used with extractors, pumps or other conduits. -block.pulse-conduit.description = Advanced liquid transport block. Transports liquids faster and stores more than standard conduits. -block.phase-conduit.description = Advanced liquid transport block. Uses power to teleport liquids to a connected phase conduit over several tiles. -block.liquid-router.description = Accepts liquids from one direction and outputs them to up to 3 other directions equally. Can also store a certain amount of liquid. Useful for splitting the liquids from one source to multiple targets. -block.liquid-tank.description = Stores a large amount of liquids. Use it for creating buffers when there is a non-constant demand of materials or as a safeguard for cooling vital blocks. -block.liquid-junction.description = Acts as a bridge for two crossing conduits. Useful in situations with two different conduits carrying different liquids to different locations. -block.bridge-conduit.description = Advanced liquid transport block. Allows transporting liquids over up to 3 tiles of any terrain or building. -block.mechanical-pump.description = A cheap pump with slow output, but no power consumption. -block.rotary-pump.description = An advanced pump which doubles up speed by using power. -block.thermal-pump.description = The ultimate pump. Three times as fast as a mechanical pump and the only pump which is able to retrieve lava. -block.router.description = Accepts items from one direction and outputs them to up to 3 other directions equally. Useful for splitting the materials from one source to multiple targets. -block.distributor.description = An advanced router which splits items to up to 7 other directions equally. -block.bridge-conveyor.description = Advanced item transport block. Allows transporting items over up to 3 tiles of any terrain or building. -block.item-source.description = Infinitely outputs items. Sandbox only. -block.liquid-source.description = Infinitely outputs liquids. Sandbox only. -block.item-void.description = Destroys any items which go into it without using power. Sandbox only. -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. +unit.reaper.name = Maut +tutorial.begin = Misi Anda untuk memusnahkan[LIGHT_GRAY] musuh[].\n\nMulai dengan[accent] menambang tembaga[]. Ketuk sekumpulan tembaga didekat inti untuk melakukannya. +tutorial.drill = Menambang manual tidak efisien.\n[accent]Bor []bisa menambang otomatis.\nTaruh satu di sekumpulan tembaga. +tutorial.conveyor = [accent]Pengantar[] digunakan untuk transportasi item ke inti.\nJejerlah pengantar dari bor ke inti. +tutorial.morecopper = Butuh lebih banyak tembaga.\n\nBisa menambang dengan manual, atau menambah banyaknya bor. +tutorial.turret = Struktur Pertahanan harus dibuat untuk menangkal [LIGHT_GRAY] musuh[].\nBangun menara "duo" dekat basemu. +tutorial.drillturret = Menara "duo" membutuhkan[accent] amunisi tembaga []untuk menembak.\nTaruh bor didekat menara untuk mengisinya dengan tembaga. +tutorial.waves = [LIGHT_GRAY] Musuh[] mendatang.\n\nLindungi intimu selama 2 gelombang. Bangun lebih banyak menara. +tutorial.lead = Banyak Sumber daya yang telah terbuka. Jelajah dan tambang[accent] timah[].\n\nTarik dari unitmu ke inti untuk mengirim sumber daya. +tutorial.smelter = Tambang dan timah adalah logam lemah.\n[accent] Paduan padat[] yang lebih unggul dibuat di peleburan.\n\nBangun satu. +tutorial.densealloy = Peleburan sekarang akan menghasilkan paduan.\nTingkatkan Produktivitas jika dibutuhkan. +tutorial.siliconsmelter = inti sekarang akan membuat[accent] drone spirit[] untuk menambang dan memperbaiki blok.\n\nPabrik untuk unit lain bisa dibuat dengan [accent] silikon.\nbuatlah pelebur silikon. +tutorial.silicondrill = Silikon membutuhkan[accent] batu bara[] dan[accent] pasir[].\nMulai dengan membuat bor. +tutorial.generator = Teknologi ini membutuhkan tenaga (listrik).\nBuatlah [accent] generator pembakar[] untuk itu. +tutorial.generatordrill = Generator pembahan membutuhkan bahan bakar.\nIsi dengan batu bara dari bor. +tutorial.node = listrik membutuhkan transportasi.\nBuatlah[accent] tiang listrik[] disebelah generator pembakarmu untuk mentransfer listrik. +tutorial.nodelink = Listrik bisa ditransfer melewati blok kondusif dan generators, atau disambungkan dengan tiang listrik.\n\nSambung listrik dengan menekan salah satu tiang listrik dan menekan generator serta pelebur silikon. +tutorial.silicon = Silikon diproduksi.\n\nDisarankan Meningkatkan produktivitas. +tutorial.daggerfactory = Bangun[accent] pabrik robot "dagger".[]\n\nIni akan berguna untuk membuat robot penyerang. +tutorial.router = Pabrik butuh sumber daya untuk berfungsi.\nBuatlah pengalih untuk mengalihkan pengantar sumber daya. +tutorial.dagger = Sambungkan tiang listrik ke pabrik.\nSaat kebutuhan dicapai, robot akan diciptakan.\n\nBuatlah bor, generator dan pengantar secukupnya. +tutorial.battle = [LIGHT_GRAY] musuh[] telah mengungkapkan inti mereka.\nHancurkan dengan unitmu dan robot dagger. +block.copper-wall.description = Blok pelindung murah.\nBerguna untuk melindungi inti dan menara di beberapa gelombang awal. +block.copper-wall-large.description = Blok pelindung murah.\nBerguna untuk melindungi inti dan menara di beberapa gelombang awal.\nSebesar 4 blok. +block.thorium-wall.description = Blok pelindung yang kuat.\npelindung bagus dari musuh. +block.thorium-wall-large.description = Blok pelindung yang kuat.\npelindung bagus dari musuh.\nSebesar 4 blok. +block.phase-wall.description = Tidak sekuat dinding thorium tetapi akan memantulkan peluru senjata jika tidak terlalu kuat. +block.phase-wall-large.description = Tidak sekuat dinding thorium tetapi akan memantulkan peluru senjata jika tidak terlalu kuat. \nSebesar 4 blok. +block.surge-wall.description = Blok pelindung terkuat.\nMempunyai kemungkinan untuk menyetrum penyerang. +block.surge-wall-large.description = Blok pelindung terkuat.\nMempunyai kemungkinan untuk menyetrum penyerang. \nSebesar 4 blok. +block.door.description = Pintu kecil yang bisa dibuka-tutup dengan menekannya.\nJika dibuka, musuh bisa masuk dan menembak. +block.door-large.description = Pintu kecil yang bisa dibuka-tutup dengan menekannya.\nJika dibuka, musuh bisa masuk dan menembak.\nSebesar 4 blok. +block.mend-projector.description = menyembuhkan blok di sekelilingnya secara berkala. +block.overdrive-projector.description = Menambah kecepatan bangunan sekitar, seperti bor dan pengantar. +block.force-projector.description = Membentuk medan gaya berbentuk segi enam disekitar, melindungi bangunan dan unit didalamnya dari tembakan. +block.shock-mine.description = Mencedera musuh yang menginjak ranjau. Hampir tak kasat mata kepada musuh. +block.duo.description = menara yang murah nan kecil. Berguna melawan unit darat. +block.scatter.description = Menara Anti-Udara berukuran sedang. Melempar gumpalan timah atau kepingan ke unit musuh. +block.arc.description = Menara kecil jarak dekat ini menembak listrik secara acak ke arah musuh. +block.hail.description = Menara meriam kecil. +block.lancer.description = Menara ukuran sedang yang menembak sinar listrik. +block.wave.description = Menara penembak beruntun ukuran sedang yang menembak gelembung air. +block.salvo.description = Menara ukuran sedang yang menembak pelurunya secara serentak. +block.swarmer.description = Menara ukuran sedang yang menembak misil bertubi-tubi. +block.ripple.description = Menara meriam besar yang menembak beberapa peluru sekaligus. +block.cyclone.description = Menara Penembak Beruntun Besar. +block.fuse.description = Menara besar ini menembak sinar pendek yang kuat. +block.spectre.description = Menara besar yang menembak dua peluru kuat sekaligus\. +block.meltdown.description = Menara besar ini menembak sinar panjang yang kuat. +block.conveyor.description = Blok transportasi dasar. Memindahkan item ke menara ataupun pabrik. Bisa Diputar. +block.titanium-conveyor.description = Blok transportasi canggih. Memindahkan item lebih cepat daripada pengantar biasa. +block.phase-conveyor.description = Blok transportasi canggih. Menggunakan tenaga untuk teleportasi item ke sambungan pengantar phase melewati beberapa blok. +block.junction.description = Berguna seperti jembatan untuk dua pengantar yang bersimpangan. Berguna di situasi dimana dua pengantar berbeda membawa bahan berbeda ke lokasi yang berbeda. +block.mass-driver.description = Blok item transportasi tercanggih. Membawa beberapa item dan menembaknya ke driver massal lainnya dari arah yang jauh. +block.silicon-smelter.description = Mengubah pasir dengan batu bara untuk memproduksi silikon. +block.plastanium-compressor.description = Memproduksi plastanium dari oli dan titanium. +block.phase-weaver.description = Memproduksi kain phase dari thorium dan banyak pasir. +block.alloy-smelter.description = Memproduksi paduan surge dari titanium, timah, silikon dan tembaga. +block.pulverizer.description = Menghancurkan kepingan menjadi pasir. Berguna jika tidak ada pasir disekitar. +block.pyratite-mixer.description = Mencampur batu bara, timah dan pasir menjadi pyratite yang sangat mudah terbakar. +block.blast-mixer.description = Menggunakan oli untuk membentuk pyratite menjadi senyawa peledak yang kurang mudah terbakar tetapi lebih eksplosif. +block.cryofluidmixer.description = Mencampur air dan titanium menjadi cryofluid yang lebih efisien untuk pendingin. +block.melter.description = Melelehkan kepingan menjadi terak untuk proses selanjutnya atau digunakan menara. +block.incinerator.description = Menghancurkan item atau zat cair sisa. +block.spore-press.description = Menekan pod spora menjadi oli. +block.separator.description = Mengekstrak logam-logam berguna dari terak. +block.power-node.description = Membawa tenaga ke tiang tersambung. hingga empat sumber listrik, sambungan atau tiang lainnya yang bisa disambung. Tiang akan mendapatkan atau memberi tenaga ke/dari blok yang disambung. +block.power-node-large.description = Mempunyai radius lebih besar dari tiang listrik biasa dan bisa menyambung hingga enam to up to six sumber listrik, sambungan atau tiang lainnya. +block.battery.description = Menyimpan tenaga jika ada kelimpahan dan memberikan tenaga jika ada kekurangan, asalkan ada kapasitas tersisa. +block.battery-large.description = Menyimpan lebih banyak tenaga daripada baterai biasa. +block.combustion-generator.description = Menghasilkan tenaga dengan membakar oli atau pembakar. +block.turbine-generator.description = Lebih efisien daripada generator pembakar, tetapi membutuhkan tambahan air. +block.thermal-generator.description = Menghasilkan tenaga disaat ditaruh di lokasi yang panas. +block.solar-panel.description = Menghasilkan jumlah tenaga kecil dari matahari. +block.solar-panel-large.description = Menghasilkan lebih banyak tenaga dari panel surya biasa, tapi lebih mahal untuk dibangun. +block.thorium-reactor.description = Menghasilkan tenaga yang besar dari konsumsi thorium. Membutuhkan pendinginan konstan. Akan meledak jika tidak cukup pendingin . Pengeluaran tenaga tergantung kepenuhan. +block.rtg-generator.description = Generator yang tidak membutuhkan pendiginan tetapi lebih memberi sedikit tenaga daripada reaktor thorium. +block.unloader.description = Mengeluarkan item dari kontainer, vault atau inti kedalam pengantar atau langsung ke blok yang dituju. Tipe item yang dimuat bisa diganti dengan mengetuk pembongkar muatan. +block.container.description = Menyimpan semua tipe item. [LIGHT_GRAY] pembongkar muatan[] bisa digunakan untuk mengeluarkan item dari kontainer. +block.vault.description = Menyimpan semua tipe item berkuantitas besar. [LIGHT_GRAY] pembongkar muatan[] bisa digunakan untuk mengeluarkan item dari vault. +block.mechanical-drill.description = Bor murah. Saat ditaruh ditempat yang sesuai, mengeluarkan item dengan pelan tanpa batas. +block.pneumatic-drill.description = Bor lebih cepat dari bor mekanik dan bisa memproses bahan lebih keras dengan menggunakan tekanan udara. +block.laser-drill.description = Mengebor lebih cepat lewat teknologi laser, tapi membutuhkan tenaga. Bisa menambang thorium dengan bor ini. +block.blast-drill.description = Bor Tercanggih. Membutuhkan banyak tenaga. +block.water-extractor.description = Mengekstrak air dari tanah. Gunakan jika tidak ada sumber air disekitar. +block.cultivator.description = Membudidaya spora kecil menjadi pod siap diolah. +block.oil-extractor.description = Menggunakan tenaga cukup besar untuk mengekstrak oli dari pasir. Gunakan jika tidak ada sumber oli disekitar. +block.trident-ship-pad.description = Tinggalkan kapalmu sekarang dan berubah menjadi pengebom kelas berat.\nGunakan pad dengan menekan dua kali sambil berdiri didalamnya. +block.javelin-ship-pad.description = Tinggalkan kapalmu sekarang dan berubah menjadi Pencegat yang kuat dan cepat dengan kekuatan listrik.\nGunakan pad dengan menekan dua kali sambil berdiri didalamnya. +block.glaive-ship-pad.description = Tinggalkan kapalmu sekarang dan berubah menjadi Pesawat tempur berbaja.\nGunakan pad dengan menekan dua kali sambil berdiri didalamnya. +block.tau-mech-pad.description = Tinggalkan kapalmu sekarang dan berubah menjadi robot pemulih yang bisa memulihkan bangunan dan unit.\nGunakan pad dengan menekan dua kali sambil berdiri didalamnya. +block.delta-mech-pad.description = Tinggalkan kapalmu sekarang dan berubah menjadi robot cepat untuk serangan tabrak-lari.\nGunakan pad dengan menekan dua kali sambil berdiri didalamnya. +block.omega-mech-pad.description = Tinggalkan kapalmu sekarang dan berubah menjadi robot besar dan berbaja, digunakan untuk serangan baris depan.\nGunakan pad dengan menekan dua kali sambil berdiri didalamnya. +block.spirit-factory.description = Memproduksi drone ringan yang menambang sumber daya dan memulih blok. +block.phantom-factory.description = Memproduksi drone canggih yang lebih efektif dibandingkan drone spirit. +block.wraith-factory.description = Memproduksi unit tabrak-lari yang cepat. +block.ghoul-factory.description = Memproduksi pengebom kelas berat. +block.dagger-factory.description = Memproduksi unit darat dasar. +block.titan-factory.description = Memproduksi unit darat canggih. +block.fortress-factory.description = Memproduksi unit meriam darat kelas berat. +block.revenant-factory.description = Memproduksi unit laser udara kelas berat. +block.repair-point.description = Terus menerus memulihkan unit terluka disekitar. +block.conduit.description = Blok Transportasi Zat Cair Umum. Bekerja Seperti Pengantar, tetapi untuk zat cair. +block.pulse-conduit.description = Blok Transportasi Zat Cair Canggih. Memindahkan dan menyimpan zat cair lebih cepat dan banyak daripada saluran biasa. +block.phase-conduit.description = Blok Transportasi Zat Cair Canggih. Menggunakan listrik untuk teleportasi zat zair ke saluran phase yang terhubung dari jarak jauh. +block.liquid-router.description = Menerima zat cair dari satu arah dan mengeluarkannya ke 3 arah yang sama. Bisa juga menyimpan sejumlah zat cair. Berguna untuk memisahkan zat cair dari satu sumber ke target yang banyak. +block.liquid-tank.description = Menyimpan jumlah zat cair yang banyak. Gunakan sebagai penyangga ketika kebutuhan zat cair tidak konstan atau sebagai penjaga untuk mendinginkan blok yang vital. +block.liquid-junction.description = Berguna seperti jembatan untuk dua saluran yang bersimpangan. Berguna di situasi dimana dua saluran berbeda membawa zat cair berbeda ke lokasi yang berbeda. +block.bridge-conduit.description = Blok Transportasi Zat Cair Canggih. bisa memindahkan zat cair hingga 3 blok panjang melewati apapun lapangan atau bangunan. +block.mechanical-pump.description = Pompa murah dengan pengeluaran yang pelan, tetapi tidak mengkonsumsi tenaga. +block.rotary-pump.description = Pompa canggih yang kecepatannya dua kali lipat jika menggunakan tenaga. +block.thermal-pump.description = Pompa Tercanggih. +block.router.description = Menerima bahan dari satu arah dan mengeluarkannya ke 3 arah yang sama. Bisa juga menyimpan sejumlah bahan. Berguna untuk memisahkan bahan dari satu sumber ke target yang banyak. +block.distributor.description = Pemisah canggih yang memisah item ke 7 arah berbeda bersamaan. +block.bridge-conveyor.description = Blok Transportasi Item Canggih. bisa memindahkan item hingga 3 blok panjang melewati apapun lapangan atau bangunan. +block.item-source.description = Mengeluarkan item tak terhingga. Sandbox eksklusif. +block.liquid-source.description = Mengeluarkan zat cair tak terhingga. Sandbox eksklusif. +block.item-void.description = Menghancurkan item apa saja tanpa penggunaan tenaga. Sandbox eksklusif. +block.power-source.description = Menghasilkan tenaga tak terbatas. Sandbox eksklusif. +block.power-void.description = Menghilangkan semua tenaga yang masuk kedalamnya. Sandbox eksklusif. +liquid.water.description = Umumnya digunakan untuk mendinginkan mesin-mesin dan pendaur ulang. +liquid.oil.description = Bisa dibakar, diledakkan atau sebagai pendigin. +liquid.cryofluid.description = Zat cair paling efisien untuk mendinginkan hal-hal. diff --git a/core/assets/bundles/bundle_ko.properties b/core/assets/bundles/bundle_ko.properties index 636749902c..622824b7bb 100644 --- a/core/assets/bundles/bundle_ko.properties +++ b/core/assets/bundles/bundle_ko.properties @@ -5,7 +5,7 @@ discord = Mindustry Discord 에 참여 해 보세요! link.discord.description = 공식 Mindustry Discord 채팅방 link.github.description = 게임 소스코드 link.dev-builds.description = 불안정한 개발 빌드들 -link.trello.description = 다음 출시될 기능들을 게시판 공식 Trello 보드 +link.trello.description = 다음 출시될 기능들을 게시한 공식 Trello 보드 link.itch.io.description = PC 버전 다운로드와 HTML5 버전이 있는 itch.io 사이트 link.google-play.description = Google Play 스토어 정보 link.wiki.description = 공식 Mindustry 위키 @@ -32,7 +32,6 @@ level.mode = 게임 모드 : showagain = 다음 세션에서 이 메세지를 표시하지 않습니다 coreattack = < 코어가 공격받고 있습니다! > nearpoint = [[ [scarlet]드롭 지점에서 나가세요[] ]\n적 스폰시 건물 및 유닛 파괴 -outofbounds = [[ 출입 금지 구역 ]\n[]{0}초후 유닛이 파괴됩니다. database = 코어 데이터베이스 savegame = 게임 저장 loadgame = 게임 불러오기 @@ -207,6 +206,7 @@ waves.copy = 클립보드로 복사 waves.load = 클립보드에서 불러오기 waves.invalid = 클립보드의 잘못된 웨이브 데이터 waves.copied = 웨이브 복사됨 +wave.none = 적이 설정되지 않음.\n빈 웨이브 설정값은 자동으로 기본 웨이브 설정값으로 바뀝니다. editor.default = [LIGHT_GRAY]<기본값> edit = 편집... editor.name = 이름: @@ -251,6 +251,20 @@ editor.mapname = 맵 이름: editor.overwrite = [accept]경고!이 명령은 기존 맵을 덮어씌우게 됩니다. editor.overwrite.confirm = [scarlet]경고![] 이 이름을 가진 맵이 이미 있습니다. 덮어 쓰시겠습니까? editor.selectmap = 불러올 맵 선택: +toolmode.replace = 재배치 +toolmode.replace.description = 블록을 배치합니다. +toolmode.replaceall = 모두 재배치 +toolmode.replaceall.description = 맵에 있는 모든 블록을 재배치합니다. +toolmode.orthogonal = 직교 +toolmode.orthogonal.description = 직교로 블록을 배치합니다. +toolmode.square = 정사각형 +toolmode.square.description = 정사각형 형태의 브러시. +toolmode.eraseores = 자원 초기화 +toolmode.eraseores.description = 자원만 초기화합니다. +toolmode.fillteams = 팀 채우기 +toolmode.fillteams.description = 블록 대신 팀 건물로 채웁니다. +toolmode.drawteams = 팀 그리기 +toolmode.drawteams.description = 블록 대신 팀 건물을 배치합니다. filters.empty = [LIGHT_GRAY]필터가 없습니다!! 아래 버튼을 눌러 추가하세요. filter.distort = 왜곡 filter.noise = 노이즈 @@ -328,6 +342,7 @@ zone.desolateRift.name = 황량한 강 zone.nuclearComplex.name = 핵 생산 단지 zone.overgrowth.name = 과성장 지역 zone.tarFields.name = 타르 지역 +zone.saltFlats.name = 갯벌 settings.language = 언어 settings.reset = 설정 초기화 settings.rebind = 키 재설정 @@ -373,7 +388,7 @@ blocks.drillspeed = 기본 드릴 속도 blocks.boosteffect = 가속 효과 blocks.maxunits = 최대 활성유닛 blocks.health = 체력 -blocks.buildtime = Build Time +blocks.buildtime = 건설 시간 blocks.inaccuracy = 오차각 blocks.shots = 발포 횟수 blocks.reload = 재장전 @@ -498,13 +513,14 @@ mode.survival.description = 이것은 일반 모드입니다. 제한된 자원 mode.sandbox.name = 샌드박스 mode.sandbox.description = 무한한 자원을 가지고 자유롭게 다음 단계를 시작할 수 있습니다. mode.pvp.name = PvP -mode.pvp.description = 실제 플레이어와 PvP를 합니다. +mode.pvp.description = 실제 플레이어와 PvP를 합니다. 맵에 적어도 2개의 다른 색상 코어가 있어야 합니다. mode.attack.name = 공격 -mode.attack.description = 적 기지를 파괴하세요. 웨이브가 없습니다. +mode.attack.description = 적 기지를 파괴하세요. 웨이브가 없습니다. 맵에 빨간팀 코어가 있어야 플레이 가능합니다. mode.custom = 커스텀 규칙 rules.infiniteresources = 무한 자원 rules.wavetimer = 웨이브 타이머 rules.waves = 웨이브 +rules.attack = 공격 모드 rules.enemyCheat = 무한 AI 자원 rules.unitdrops = 유닛 드롭 rules.unitbuildspeedmultiplier = 유닛 제조속도 배수 @@ -539,6 +555,7 @@ item.lead.description = 쉽게 구할 수 있으며, 전자 및 액체 수송 item.coal.name = 석탄 item.coal.description = 흔하고 쉽게 구할 수 있는 연료. item.graphite.name = 흑연 +item.graphite.description = 탄약 및 전기 절연에 사용되는 광물질화 탄소. item.titanium.name = 티타늄 item.titanium.description = 파이프 재료나 고급 드릴, 비행기/기체 등에서 재료로 사용되는 자원입니다. item.thorium.name = 토륨 @@ -638,7 +655,7 @@ block.graphite-press.name = 흑연 압축기 block.multi-press.name = 다중 압축기 block.constructing = {0} [LIGHT_GRAY](만드는중) block.spawn.name = 적 스폰지점 -block.core-shard.name = 코어-공유 +block.core-shard.name = 코어-조각 block.core-foundation.name = 코어-기초 block.core-nucleus.name = 코어-핵 block.deepwater.name = 깊은물 @@ -756,8 +773,9 @@ block.blast-mixer.name = 폭발물 혼합기 block.solar-panel.name = 태양 전지판 block.solar-panel-large.name = 대형 태양 전지판 block.oil-extractor.name = 석유 추출기 -block.spirit-factory.name = 스피릿 드론 공장 -block.phantom-factory.name = 팬텀 드론 공장 +block.draug-factory.name = 드라우그 광부 드론 공장 +block.spirit-factory.name = 스피릿 수리 드론 공장 +block.phantom-factory.name = 팬텀 건설 드론 공장 block.wraith-factory.name = 유령 전투기 공장 block.ghoul-factory.name = 구울 폭격기 공장 block.dagger-factory.name = 디거 기체 공장 @@ -802,10 +820,10 @@ team.orange.name = 오렌지팀 team.none.name = 공기팀 team.green.name = 그린팀 team.purple.name = 보라색팀 -unit.spirit.name = 스피릿 드론 -unit.spirit.description = 기본 드론 유닛. 기본적으로 코어에서 1개가 스폰됩니다.\n자동으로 채광하며 아이템을 수집하고, 블록을 수리합니다. -unit.phantom.name = 팬텀 드론 -unit.phantom.description = 첨단 드론 유닛.\n광석을 자동으로 채광하며, 아이템을 수집하고 블록을 수리합니다. 일반 드론보다 훨씬 효과적입니다. +unit.spirit.name = 스피릿 수리 드론 +unit.spirit.description = 블록을 자동으로 수리합니다. +unit.phantom.name = 팬텀 건설 드론 +unit.phantom.description = 첨단 드론 유닛. 플레이어의 건설을 도와줍니다. unit.dagger.name = 디거 unit.dagger.description = 기본 지상 유닛입니다.\n플레이어 기체처럼 드론을 소환하지는 않습니다. unit.crawler.name = 크롤러 diff --git a/core/assets/bundles/bundle_pl.properties b/core/assets/bundles/bundle_pl.properties index 2bc43010e6..623210a1d7 100644 --- a/core/assets/bundles/bundle_pl.properties +++ b/core/assets/bundles/bundle_pl.properties @@ -21,7 +21,7 @@ stat.built = Budynki zbudowane:[accent] {0} stat.destroyed = Budynki zniszczone:[accent] {0} stat.deconstructed = Budynki zrekonstruowane:[accent] {0} stat.delivered = Surowce wystrzelone: -stat.rank = Final Rank: [accent]{0} +stat.rank = Ocena: [accent]{0} placeline = You have selected a block.\nYou can[accent] place in a line[] by[accent] holding down your finger for a few seconds[] and dragging in a direction.\nTry it. removearea = You have selected removal mode.\nYou can[accent] remove blocks in a rectangle[] by[accent] holding down your finger for a few seconds[] and dragging.\nTry it. launcheditems = [accent]Wystrzelone przedmioty @@ -192,7 +192,7 @@ editor.author = Autor: editor.description = Opis: editor.waves = Fale: editor.rules = Rules: -editor.ingame = Edit In-Game +editor.ingame = Edytuj w grze waves.title = Fale waves.remove = Usuń waves.never = @@ -207,6 +207,7 @@ waves.copy = Kopiuj do schowka waves.load = Załaduj ze schowka waves.invalid = Invalid waves in clipboard. waves.copied = Fale zostały skopiowane. +waves.none = No enemies defined.\nNote that empty wave layouts will automatically be replaced with the default layout. editor.default = [LIGHT_GRAY] edit = Edytuj... editor.name = Nazwa: @@ -251,7 +252,22 @@ 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: -filters.empty = [LIGHT_GRAY]Bez filtrów! Dodaj jeden za pomocą przycisku poniżej. + +toolmode.replace = Replace +toolmode.replace.description = Draws only on solid blocks. +toolmode.replaceall = Replace All +toolmode.replaceall.description = Replace all blocks in map. +toolmode.orthogonal = Orthogonal +toolmode.orthogonal.description = Draws only orthogonal lines. +toolmode.square = Square +toolmode.square.description = Square brush. +toolmode.eraseores = Erase Ores +toolmode.eraseores.description = Erase only ores. +toolmode.fillteams = Fill Teams +toolmode.fillteams.description = Fill teams instead of blocks. +toolmode.drawteams = Draw Teams +toolmode.drawteams.description = Draw teams instead of blocks. +filters.empty = [LIGHT_GRAY]Brak filtrów! Dodaj jeden za pomocą przycisku poniżej. filter.distort = Distort filter.noise = Szum filter.ore = Ruda @@ -260,7 +276,7 @@ filter.scatter = Zozprosz filter.terrain = Teren filter.option.scale = Skala filter.option.chance = Szansa -filter.option.mag = Magnitude +filter.option.mag = Magnituda filter.option.threshold = Próg filter.option.circle-scale = Skala koła filter.option.octaves = Oktawy @@ -271,8 +287,9 @@ filter.option.wall = Ściana filter.option.ore = Ruda filter.option.floor2 = Druga podłoga filter.option.threshold2 = Secondary Threshold -filter.option.radius = Radius +filter.option.radius = Zasięg filter.option.percentile = Percentile + width = Szerokość: height = Wysokość: menu = Menu @@ -328,6 +345,7 @@ zone.desolateRift.name = Ponura Szczelina zone.nuclearComplex.name = Centrum Wyrobu Jądrowego zone.overgrowth.name = Overgrowth zone.tarFields.name = Tar Fields +zone.saltFlats.name = Salt Flats [scarlet][[WIP] settings.language = Język settings.reset = Przywróć domyślne settings.rebind = Zmień @@ -366,14 +384,14 @@ blocks.itemcapacity = Pojemność przedmiotów blocks.basepowergeneration = Podstawowa generacja mocy blocks.productiontime = Czas produkcji blocks.repairtime = Czas pełnej naprawy bloku -blocks.speedincrease = Speed Increase +blocks.speedincrease = Zwiększenie prędkości blocks.range = Zasięg blocks.drilltier = Co może wykopać blocks.drillspeed = Postawowa szybkość kopania blocks.boosteffect = Efekt wzmocnienia blocks.maxunits = Maksymalna ilość jednostek blocks.health = Zdrowie -blocks.buildtime = Build Time +blocks.buildtime = Czas budowy blocks.inaccuracy = Niedokładność blocks.shots = Strzały blocks.reload = Strzałów/sekundę @@ -443,7 +461,7 @@ setting.sensitivity.name = Czułość kontrolera setting.saveinterval.name = Interwał automatycznego zapisywania setting.seconds = Sekundy setting.fullscreen.name = Pełny ekran -setting.borderlesswindow.name = Borderless Window[LIGHT_GRAY] (may require restart) +setting.borderlesswindow.name = Bezramkowe okno[LIGHT_GRAY] (może wymagać restartu) setting.fps.name = Pokazuj FPS setting.vsync.name = Synchronizacja pionowa setting.lasers.name = Pokaż lasery zasilające @@ -507,26 +525,26 @@ rules.wavetimer = Zegar fal rules.waves = Fale rules.enemyCheat = Nieskończone zasoby komputera-przeciwnika (czerwonego zespołu) rules.unitdrops = Unit Drops -rules.unitbuildspeedmultiplier = Unit Creation Speed Multiplier -rules.unithealthmultiplier = Unit Health Multiplier -rules.playerhealthmultiplier = Player Health Multiplier -rules.playerdamagemultiplier = Player Damage Multiplier -rules.unitdamagemultiplier = Unit Damage Multiplier +rules.unitbuildspeedmultiplier = Mnożnik Prędkości Tworzenia Jednostek +rules.unithealthmultiplier = Mnożnik Życia Jednostek +rules.playerhealthmultiplier = Mnożnik Życia Gracza +rules.playerdamagemultiplier = Mnożnik Obrażeń Gracza +rules.unitdamagemultiplier = Mnożnik Obrażeń Jednostek rules.enemycorebuildradius = Enemy Core No-Build Radius:[LIGHT_GRAY] (tiles) rules.respawntime = Respawn Time:[LIGHT_GRAY] (sec) -rules.wavespacing = Wave Spacing:[LIGHT_GRAY] (sec) -rules.buildcostmultiplier = Build Cost Multiplier -rules.buildspeedmultiplier = Build Speed Multiplier -rules.waitForWaveToEnd = Waves wait for enemies +rules.wavespacing = Odstępy między falami:[LIGHT_GRAY] (sek) +rules.buildcostmultiplier = Mnożnik Kosztów Budowania +rules.buildspeedmultiplier = Mnożnik Prędkości Budowania +rules.waitForWaveToEnd = Fale czekają na przeciwników rules.dropzoneradius = Drop Zone Radius:[LIGHT_GRAY] (tiles) -rules.respawns = Max respawns per wave -rules.limitedRespawns = Limit Respawns -rules.title.waves = Waves -rules.title.respawns = Respawns -rules.title.resourcesbuilding = Resources & Building -rules.title.player = Players -rules.title.enemy = Enemies -rules.title.unit = Units +rules.respawns = Maksymalna ilośc odrodzeń na falę +rules.limitedRespawns = Ogranicz Odrodzenia +rules.title.waves = Fale +rules.title.respawns = Odrodzenia +rules.title.resourcesbuilding = Zasoby i Budowanie +rules.title.player = Gracze +rules.title.enemy = Przeciwnicy +rules.title.unit = Jednostki content.item.name = Przedmioty content.liquid.name = Płyny content.unit.name = Jednostki @@ -539,6 +557,7 @@ item.lead.description = Podstawowy matriał. Używany w przesyle przemiotów i p item.coal.name = Węgiel item.coal.description = Zwykły i łatwo dostępny materiał energetyczny. item.graphite.name = Grafit +item.graphite.description = Mineralized carbon, used for ammunition and electrical insulation. item.titanium.name = Tytan item.titanium.description = Rzadki i bardzo lekki materiał. Używany w bardzo zaawansowanym przewodnictwie, wiertłach i samolotach. Poczuj się jak Tytan! item.thorium.name = Uran @@ -611,19 +630,19 @@ mech.buildspeed = [LIGHT_GRAY]Building Speed: {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.saltrocks.name = Salt Rocks +block.grass.name = Trawa +block.salt.name = Sól +block.saltrocks.name = Skały Solne block.pebbles.name = Pebbles block.tendrils.name = Tendrils -block.sandrocks.name = Sand Rocks +block.sandrocks.name = Skały Piaskowe block.spore-pine.name = Spore Pine block.sporerocks.name = Spore Rocks -block.rock.name = Rock -block.snowrock.name = Snow Rock +block.rock.name = Skały +block.snowrock.name = Skały śnieżne block.shale.name = Shale block.shale-boulder.name = Shale Boulder -block.moss.name = Moss +block.moss.name = Mech block.shrubs.name = Shrubs block.spore-moss.name = Spore Moss block.shalerocks.name = Shale Rocks @@ -633,7 +652,7 @@ block.scrap-wall-huge.name = Huge Scrap Wall block.scrap-wall-gigantic.name = Gigantic Scrap Wall block.thruster.name = Thruster block.kiln.name = Wypalarka -block.kiln.description = Stapia ołów i piasek na metaszkło. Wymaga małą ilość energii. +block.kiln.description = Stapia ołów i piasek na metaszkło. Wymaga małej ilości energii. block.graphite-press.name = Grafitowa Prasa block.multi-press.name = Multi-Prasa block.constructing = {0} [LIGHT_GRAY](Budowa) @@ -656,20 +675,20 @@ block.sand-water.name = Sand water block.darksand-water.name = Dark Sand Water block.char.name = Char block.holostone.name = Holo stone -block.ice-snow.name = Ice Snow -block.rocks.name = Rocks -block.icerocks.name = Ice rocks -block.snowrocks.name = Snow Rocks +block.ice-snow.name = Lodowy Śnieg +block.rocks.name = Skały +block.icerocks.name = Lodowe skały +block.snowrocks.name = Śnieżne Skały block.dunerocks.name = Dune Rocks 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.metal-floor.name = Metal Floor -block.metal-floor-2.name = Metal Floor 2 -block.metal-floor-3.name = Metal Floor 3 -block.metal-floor-5.name = Metal Floor 5 -block.metal-floor-damaged.name = Metal Floor Damaged +block.metal-floor.name = Metalowa Podłoga +block.metal-floor-2.name = Metalowa Podłoga 2 +block.metal-floor-3.name = Metalowa Podłoga 3 +block.metal-floor-5.name = Metalowa Podłoga 5 +block.metal-floor-damaged.name = Uszkodzona Metalowa Podłoga block.dark-panel-1.name = Dark Panel 1 block.dark-panel-2.name = Dark Panel 2 block.dark-panel-3.name = Dark Panel 3 @@ -692,8 +711,8 @@ 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.scorch.name = Scorch -block.scatter.name = Scatter +block.scorch.name = Płomień +block.scatter.name = Flak block.hail.name = Hail block.lancer.name = Lancer block.conveyor.name = Przenośnik @@ -756,12 +775,13 @@ block.blast-mixer.name = Wybuchowy Mieszacz block.solar-panel.name = Panel Słoneczny block.solar-panel-large.name = Duży Panel Słoneczny block.oil-extractor.name = Ekstraktor Ropy +block.draug-factory.name = Draug Miner Drone Factory block.spirit-factory.name = Fabryka Dronów Duch 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.crawler-factory.name = Fabryka Mechów Crawler 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 @@ -790,7 +810,7 @@ block.overdrive-projector.name = Projektor Nad-prędkości block.force-projector.name = Projektor Pola Siłowego block.arc.name = Piorun block.rtg-generator.name = Generator RTG -block.spectre.name = Spectre +block.spectre.name = Huragan block.meltdown.name = Meltdown block.container.name = Kontener block.launch-pad.name = Skocznia @@ -803,6 +823,7 @@ team.none.name = szary team.green.name = zielony team.purple.name = fioletowy unit.spirit.name = Duch +unit.draug.name = Draug Miner Drone unit.spirit.description = Początkowy dron. Rdzeń zawsze tworzy jeden. Wydobywa surowce, naprawia budynki oraz pomaga przy budowie. unit.phantom.name = Widmo unit.phantom.description = Zaawansowany dron. Wydobywa surowce, naprawia budynki oraz pomaga przy budowie szybciej niż dron Duch. @@ -823,14 +844,14 @@ unit.chaos-array.name = Kolejka Chaosu unit.eradicator.name = Niszczyciel unit.lich.name = Obudzony unit.reaper.name = Żeniec -tutorial.begin = Your mission here is to eradicate the[LIGHT_GRAY] enemy[].\n\nBegin by[accent] mining copper[]. Tap a copper ore vein near your core to do this. -tutorial.drill = Mining manually is inefficient.\n[accent]Drills []can mine automatically.\nPlace one on a copper vein. -tutorial.conveyor = [accent]Conveyors[] are used to transport items to the core.\nMake a line of conveyors from the drill to the core. -tutorial.morecopper = More copper is required.\n\nEither mine it manually, or place more drills. -tutorial.turret = Defensive structures must be built to repel the[LIGHT_GRAY] enemy[].\nBuild a duo turret near your base. -tutorial.drillturret = Duo turrets require[accent] copper ammo []to shoot.\nPlace a drill next to the turret to supply it with mined copper. -tutorial.waves = The[LIGHT_GRAY] enemy[] approaches.\n\nDefend your core for 2 waves. Build more turrets. -tutorial.lead = More ores are available. Explore and mine[accent] lead[].\n\nDrag from your unit to the core to transfer resources. +tutorial.begin = Twoją misją jest zniszczenie[LIGHT_GRAY] wrogów[].\n\nZacznij od[accent] wydobycia miedzi[]. Kliknij na rudę miedzi w pobliżu swojego rdzenia, aby to zrobić. +tutorial.drill = Kopanie ręcznie nie jest efektywne.\n[accent]Wiertła []mogą kopać automatycznie.\nPostaw je na rudzie miedzi. +tutorial.conveyor = [accent]Transportery[] są używane do przenoszenia przedmiotów do rdzenia.\nZrób linię z transporterów z wiertła do rdzenia. +tutorial.morecopper = Potrzebne jest więcej miedzi!\n\Kop ręcznie, albo postaw więcej wierteł. +tutorial.turret = Struktury obronne muszą być wybudowane, aby odpychać [LIGHT_GRAY] wrogów[].\nZbuduj podwójne działko niedaleko swojej bazy. +tutorial.drillturret = Podwójne działko wymaga[accent] miedzi []jako amunicji, aby strzelać.\nPostaw wiertło obok działka, aby zaopatrzyć je w miedź. +tutorial.waves = The[LIGHT_GRAY] Wrogowie[] nadciągają.\n\nObroń swój rdzeń przez dwie fale. Wybuduj więcej działek. +tutorial.lead = Dostępne jest więcej rud - eksploruj i wydobądź[accent] ołów[].\n\nPrzeciągnij ze swojej jednostki do rdzenia, aby przenieść zasoby. tutorial.smelter = Copper and lead are weak metals.\nSuperior[accent] Dense Alloy[] can be created in a smelter.\n\nBuild one. tutorial.densealloy = The smelter will now produce alloy.\nGet some.\nImprove the production if necessary. tutorial.siliconsmelter = The core will now create a[accent] spirit drone[] for mining and repairing blocks.\n\nFactories for other units can be created with [accent] silicon.\nMake a silicon smelter. @@ -923,17 +944,17 @@ 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. -block.conduit.description = Basic liquid transport block. Works like a conveyor, but with liquids. Best used with extractors, pumps or other conduits. +block.repair-point.description = Bez przerw ulecza najbliższą zniszczoną jednostkę w jego zasięgu. +block.conduit.description = Podstawowy blok do przenoszenia cieczy. Działa jak transporter, ale na ciecze. Najlepiej używać z ekstraktorami wody, pompami lub innymi rurami. block.pulse-conduit.description = Zaawansowany blok do przenoszenia cieczy. Transportuje je szybciej i magazynuje więcej niż standardowe rury. -block.phase-conduit.description = Zaawansowany blok do przenoszenia cieczy. Używa prądu, aby przenieść ciecz do połączonego phase conduit przez kilka bloków. -block.liquid-router.description = Accepts liquids from one direction and outputs them to up to 3 other directions equally. Can also store a certain amount of liquid. Useful for splitting the liquids from one source to multiple targets. -block.liquid-tank.description = Stores a large amount of liquids. Use it for creating buffers when there is a non-constant demand of materials or as a safeguard for cooling vital blocks. +block.phase-conduit.description = Zaawansowany blok do przenoszenia cieczy. Używa prądu, aby przenieść ciecz do połączonego transportera fazowego przez kilka bloków. +block.liquid-router.description = Akceptuje płyny z jednego kierunku i wyprowadza je do trzech innych kierunków jednakowo. Może również przechowywać pewną ilość płynu. Przydatne do dzielenia płynów z jednego źródła na wiele celów. +block.liquid-tank.description = Magazynuje ogromne ilości cieczy. Użyj go do stworzenia buforu, gdy występuje różne zapotrzebowanie na materiały lub jako zabezpieczenie dla chłodzenia ważnych bloków. block.liquid-junction.description = Działa jak most dla dwóch krzyżujących się rur. Przydatne w sytuacjach, kiedy dwie rury mają różne ciecze do różnych lokacji. block.bridge-conduit.description = Zaawansowany blok przenoszący ciecze. Pozwala na przenoszenie cieczy nawet do 3 bloków na każdym terenie, przez każdy budynek. block.mechanical-pump.description = Tania pompa o niskiej przepustowości. Nie wymaga prądu. block.rotary-pump.description = Zaawansowana pompa, dwukrotnie większa przepustowość od mechanicznej pompy. Wymaga prądu. -block.thermal-pump.description = The ultimate pump. Three times as fast as a mechanical pump and the only pump which is able to retrieve lava. +block.thermal-pump.description = Najlepsza pompa. Trzy razy szybsza od mechanicznej pompy i jedyna, która może wypompować lawę. block.router.description = Akceptuje przedmioty z jednego miejsca i rozdziela je do trzech innych kierunków. Przydatne w rozdzielaniu materiałów z jednego źródła do wielu celów. block.distributor.description = Zaawansowany rozdzielacz, rozdzielający przedmioty do 7 innych kierunków. block.bridge-conveyor.description = Zaawansowany blok transportujący. Pozwala na przenoszenie przedmiotów nawet do 3 bloków na każdym terenie, przez każdy budynek. diff --git a/core/assets/bundles/bundle_pt_BR.properties b/core/assets/bundles/bundle_pt_BR.properties index 107330d9f0..0c32fa22d9 100644 --- a/core/assets/bundles/bundle_pt_BR.properties +++ b/core/assets/bundles/bundle_pt_BR.properties @@ -11,11 +11,11 @@ link.google-play.description = Listamento do google play store link.wiki.description = Wiki oficial do Mindustry linkfail = Falha ao abrir o link\nO Url foi copiado screenshot = Screenshot salvo para {0} -screenshot.invalid = Map too large, potentially not enough memory for screenshot. +screenshot.invalid = Mapa grande demais, Potencialmente sem memoria suficiente para captura. gameover = O núcleo foi destruído. gameover.pvp = O time[accent] {0}[] É vitorioso! highscore = [YELLOW]Novo recorde! -stat.wave = Ondas derrotadas:[accent] {0} +stat.wave = Hordas derrotadas:[accent] {0} stat.enemiesDestroyed = Enimigos Destruídos:[accent] {0} stat.built = Construções construídas:[accent] {0} stat.destroyed = Construções destruídas:[accent] {0} @@ -24,14 +24,14 @@ stat.delivered = Recursos lançados: stat.rank = Rank Final: [accent]{0} placeline = Você selecionou um bloco.\nVocê pode[accent] colocar uma linha[] por[accent] carregar o seu dedo por alguns segundos[] e arrastar em uma direção.\nTente. removearea = Você selecionou o modo de remoção.\nVocê pode[accent] remover blocos dentro de um retângulo[] por[accent] carregar o seu dedo por alguns segundos[] e arrastar.\nTente. -launcheditems = [accent]Launched Items +launcheditems = [accent]Itens lançados map.delete = Certeza que quer deletar o mapa "[accent]{0}[]"? level.highscore = Melhor\npontuação: [accent] {0} level.select = Seleção de Fase level.mode = Modo de Jogo: showagain = Não mostrar na proxima sessão coreattack = < O núcleo está sobre ataque! > -nearpoint = [[ [scarlet]SAIA DO PONTO DE SPAWN IMEDIATAMENTE[] ]\naniquilação iminente +nearpoint = [[ [scarlet]SAIA DO PONTO DE SPAWN IMEDIATAMENTE[] ]\nANIQUILAÇÃO IMINENTE outofbounds = [[ OUT OF BOUNDS ]\n[]auto destruição em {0} database = banco do núcleo savegame = Salvar Jogo @@ -41,7 +41,7 @@ addplayers = Adicionar/Remover Jogador customgame = Jogo Customizado newgame = Novo Jogo none = -minimap = MiniMapa +minimap = Mini-Mapa close = Fechar quit = Sair maps = Mapas @@ -77,7 +77,7 @@ hostserver = Hospedar servidor hostserver.mobile = Hospedar\nJogo host = Hospedar hosting = [accent]Abrindo server... -hosts.refresh = atualizar +hosts.refresh = Atualizar hosts.discovering = Descobrindo jogos em lan server.refreshing = Atualizando servidor hosts.none = [lightgray]Nenhum jogo lan encontrado! @@ -191,13 +191,13 @@ editor.mapinfo = Informação do mapa editor.author = Autor: editor.description = Descrição: editor.waves = Ondas: -editor.rules = Rules: -editor.ingame = Edit In-Game -waves.title = Ondas +editor.rules = Regras: +editor.ingame = Editar em-jogo +waves.title = Hordas waves.remove = Remover waves.never = -waves.every = a casa -waves.waves = ondas(s) +waves.every = a cada +waves.waves = Hordas(s) waves.perspawn = por spawn waves.to = para waves.boss = Chefe @@ -210,23 +210,23 @@ waves.copied = Ondas copiadas. editor.default = [LIGHT_GRAY] edit = Editar... editor.name = Nome: -editor.spawn = Spawn Unit -editor.removeunit = Remove Unit +editor.spawn = Criar unidade +editor.removeunit = Remover unidade editor.teams = Time editor.elevation = Elevação editor.errorload = Erro carregando arquivo:\n[accent]{0} editor.errorsave = Erro salvando arquivo:\n[accent]{0} -editor.errorimage = That's an image, not a map. Don't go around changing extensions expecting it to work.\n\nIf you want to import a legacy map, use the 'import legacy map' button in the editor. -editor.errorlegacy = This map is too old, and uses a legacy map format that is no longer supported. -editor.errorheader = This map file is either not valid or corrupt. +editor.errorimage = Isso é uma imagem, Não um mapa. Não vá por aí mudando extensões esperando que funcione.\n\nSe você quer importar um mapa legacy, Use o botão 'Importar mapa legacy'no editor. +editor.errorlegacy = Esse mapa é velho demais, E usa um formato de mapa legacy que não é mais suportado. +editor.errorheader = Este arquivo de mapa não é mais valido, Ou esta corrompido. editor.errorname = Mapa não tem nome definido. editor.update = atualizar editor.randomize = Randomizar editor.apply = Aplicar editor.generate = Gerar editor.resize = Redimen\n sionar -editor.loadmap = Carregar\n Mapa -editor.savemap = Salvar\n Mapa +editor.loadmap = Carregar\nMapa +editor.savemap = Salvar\nMapa editor.saved = Salvo! editor.save.noname = Seu mapa não tem um nome! Coloque um no menu de "Informação do mapa" editor.save.overwrite = O seu mapa Substitui um mapa já construído! Coloque um nome diferente no menu "Informação do mapa" @@ -264,15 +264,15 @@ filter.option.mag = Magnitude filter.option.threshold = Margem filter.option.circle-scale = Escala de círculo filter.option.octaves = Oitavas -filter.option.falloff = Falloff +filter.option.falloff = Caída filter.option.block = Bloco filter.option.floor = Chão filter.option.wall = Parede filter.option.ore = Minério -filter.option.floor2 = Chão decundário +filter.option.floor2 = Chão secundário filter.option.threshold2 = Margem secundária filter.option.radius = Radius -filter.option.percentile = Percentile +filter.option.percentile = Percentil width = Largura: height = Altura: menu = Menu @@ -301,7 +301,7 @@ launch.next = [LIGHT_GRAY]próxima oportunidade na onda {0} launch.unable = [scarlet]Incapaz de LANÇAR.[] Enimigos. launch.confirm = Isto vai lançar todos os seus recursos no seu núcleo.\nVoce não será capaz de retornar para esta base. uncover = Descobrir -configure = Configurar loadout +configure = Configurar carregamento configure.locked = [LIGHT_GRAY]Alcançe a onda {0}\npara Configurar o Loadout. zone.unlocked = [LIGHT_GRAY]{0} Desbloqueado. zone.requirement.complete = Onda {0} alcançada:\n{1} Requerimentos da zona alcançada. @@ -319,15 +319,15 @@ error.mapnotfound = Arquivo de mapa não encontrado! error.io = Erro I/O de internet. error.any = Erro de rede desconhecido. zone.groundZero.name = Marco zero -zone.desertWastes.name = Desert Wastes +zone.desertWastes.name = Perdas do Deserto zone.craters.name = As crateras zone.frozenForest.name = Floresta congelada zone.ruinousShores.name = Costas Ruinosas zone.stainedMountains.name = Montanhas manchadas zone.desolateRift.name = Fenda desolada zone.nuclearComplex.name = Complexo de construção nuclear -zone.overgrowth.name = Overgrowth -zone.tarFields.name = Tar Fields +zone.overgrowth.name = SobreCrescido +zone.tarFields.name = Campos de Tar settings.language = Linguagem settings.reset = Restaurar Padrões settings.rebind = Religar @@ -373,7 +373,7 @@ blocks.drillspeed = Velocidade da furadeira base blocks.boosteffect = Efeito do Boost blocks.maxunits = Maximo de unidades ativas blocks.health = Saúde -blocks.buildtime = Build Time +blocks.buildtime = Tempo de construção blocks.inaccuracy = Imprecisão blocks.shots = Tiros blocks.reload = Recarregar @@ -382,7 +382,7 @@ bar.drillspeed = Velocidade da furadeira: {0}/s bar.efficiency = Eficiencia: {0}% bar.powerbalance = Energia: {0} bar.poweramount = Energia: {0} -bar.poweroutput = Saida de energia: {0} +bar.poweroutput = Saída de energia: {0} bar.items = Itens: {0} bar.liquid = Liquido bar.heat = Aquecimento @@ -394,13 +394,13 @@ bullet.splashdamage = [stat]{0}[lightgray] Dano em area ~[stat] {1}[lightgray] B bullet.incendiary = [stat]incendiario bullet.homing = [stat]Guiado bullet.shock = [stat]Choque -bullet.frag = [stat]fraguimento +bullet.frag = [stat]fragmento bullet.knockback = [stat]{0}[lightgray] Impulso bullet.freezing = [stat]Congelamento bullet.tarred = [stat]tarred bullet.multiplier = [stat]{0}[lightgray]x Multiplicador de munição bullet.reload = [stat]{0}[lightgray]x recarregar -unit.blocks = blocos +unit.blocks = Blocos unit.powersecond = Unidades de energia/segundo unit.liquidsecond = Unidades de líquido/segundo unit.itemssecond = itens/segundo @@ -431,11 +431,11 @@ setting.fpscap.name = FPS Maximo setting.fpscap.none = Nenhum setting.fpscap.text = {0} FPS setting.swapdiagonal.name = Sempre colocação diagnoal -setting.difficulty.training = treinamento +setting.difficulty.training = Treinamento setting.difficulty.easy = Fácil setting.difficulty.normal = Normal setting.difficulty.hard = Difícil -setting.difficulty.insane = insano +setting.difficulty.insane = Insano setting.difficulty.name = Dificuldade setting.screenshake.name = Balanço da Tela setting.effects.name = Efeitos @@ -443,7 +443,7 @@ setting.sensitivity.name = Sensibilidade do Controle setting.saveinterval.name = Intervalo de autosalvamento setting.seconds = {0} Segundos setting.fullscreen.name = Tela Cheia -setting.borderlesswindow.name = Borderless Window[LIGHT_GRAY] (may require restart) +setting.borderlesswindow.name = Janela sem borda[LIGHT_GRAY] (Pode precisar reeiniciar) setting.fps.name = Mostrar FPS setting.vsync.name = VSync setting.lasers.name = Mostrar lasers @@ -454,8 +454,8 @@ setting.mutemusic.name = Desligar Música setting.sfxvol.name = Volume de Efeitos setting.mutesound.name = Desligar Som setting.crashreport.name = Enviar denuncias de crash anonimas -setting.chatopacity.name = Chat Opacity -setting.playerchat.name = Display In-Game Chat +setting.chatopacity.name = Opacidade do chat +setting.playerchat.name = Mostrar chat em-jogo keybind.title = Refazer teclas category.general.name = Geral category.view.name = Ver @@ -467,7 +467,7 @@ keybind.gridMode.name = Seleção de blocos keybind.gridModeShift.name = Seleção de categoria keybind.press = Pressione uma tecla... keybind.press.axis = Pressione uma Axis ou tecla... -keybind.screenshot.name = Map Screenshot +keybind.screenshot.name = Captura do mapa keybind.move_x.name = mover_x keybind.move_y.name = mover_y keybind.select.name = selecionar @@ -500,31 +500,31 @@ mode.sandbox.description = Recursos infinitos E sem tempo para Ataques. mode.pvp.name = PvP mode.pvp.description = Lutar contra outros jogadores locais. mode.attack.name = Ataque -mode.attack.description = Sem ondas, Com o objetivo de destruir a base inimiga. +mode.attack.description = Sem hordas, Com o objetivo de destruir a base inimiga. mode.custom = Regras personalizadas rules.infiniteresources = Recursos infinitos -rules.wavetimer = Tempo de onda -rules.waves = Ondas +rules.wavetimer = Tempo de horda +rules.waves = Hordas rules.enemyCheat = Recursos de IA Infinitos -rules.unitdrops = Unidade droppa +rules.unitdrops = Unidade solta rules.unitbuildspeedmultiplier = Multiplicador de velocidade de criação de unidade rules.unithealthmultiplier = Multiplicador de vida de unidade -rules.playerhealthmultiplier = Player Health Multiplier -rules.playerdamagemultiplier = Player Damage Multiplier -rules.unitdamagemultiplier = Unit Damage Multiplier -rules.enemycorebuildradius = Raio de "Não-criação" de core inimigo:[LIGHT_GRAY] (tiles) -rules.respawntime = Tempo de renascimento:[LIGHT_GRAY] (sec) -rules.wavespacing = Espaço entre waves:[LIGHT_GRAY] (sec) +rules.playerhealthmultiplier = Multiplicador da vida de jogador +rules.playerdamagemultiplier = Multiplicador do dano de jogador +rules.unitdamagemultiplier = Multiplicador de dano de Unidade +rules.enemycorebuildradius = Raio de "Não-criação" de core inimigo:[LIGHT_GRAY] (blocos) +rules.respawntime = Tempo de renascimento:[LIGHT_GRAY] (seg) +rules.wavespacing = Espaço entre hordas:[LIGHT_GRAY] (seg) rules.buildcostmultiplier = Multiplicador de custo de construção rules.buildspeedmultiplier = Multiplicador de velocidade de construção -rules.waitForWaveToEnd = Waves wait for enemies -rules.dropzoneradius = Drop Zone Radius:[LIGHT_GRAY] (tiles) -rules.respawns = Max respawns per wave -rules.limitedRespawns = Limit Respawns -rules.title.waves = Waves +rules.waitForWaveToEnd = hordas esperam inimigos +rules.dropzoneradius = Zona de soltá:[LIGHT_GRAY] (blocos) +rules.respawns = Respawn maximos por horda +rules.limitedRespawns = Respawn limitados +rules.title.waves = Hordas rules.title.respawns = Respawns rules.title.resourcesbuilding = Recursos e Construções -rules.title.player = Players +rules.title.player = Jogadores rules.title.enemy = Inimigos rules.title.unit = Unidades content.item.name = Itens @@ -602,7 +602,7 @@ item.radioactivity = [LIGHT_GRAY]RadioAtividade: {0} unit.health = [LIGHT_GRAY]Vida: {0} unit.speed = [LIGHT_GRAY]Velocidade: {0} mech.weapon = [LIGHT_GRAY]Arma: {0} -mech.health = [LIGHT_GRAY]Saude: {0} +mech.health = [LIGHT_GRAY]Saúde: {0} mech.itemcapacity = [LIGHT_GRAY]Capacidade de itens: {0} mech.minespeed = [LIGHT_GRAY]Velocidade de mineração: {0} mech.minepower = [LIGHT_GRAY]Poder de mineração: {0} @@ -670,13 +670,13 @@ block.metal-floor-2.name = Chão de metal 2 block.metal-floor-3.name = Chão de metal 3 block.metal-floor-5.name = Chão de metal 5 block.metal-floor-damaged.name = Chão de metal danificado -block.dark-panel-1.name = Dark Panel 1 -block.dark-panel-2.name = Dark Panel 2 -block.dark-panel-3.name = Dark Panel 3 -block.dark-panel-4.name = Dark Panel 4 -block.dark-panel-5.name = Dark Panel 5 -block.dark-panel-6.name = Dark Panel 6 -block.dark-metal.name = Dark Metal +block.dark-panel-1.name = Painel escuro 1 +block.dark-panel-2.name = Painel escuro 2 +block.dark-panel-3.name = Painel escuro 3 +block.dark-panel-4.name = Painel escuro 4 +block.dark-panel-5.name = Painel escuro 5 +block.dark-panel-6.name = Painel escuro 6 +block.dark-metal.name = Metal escuro block.ignarock.name = Rocha igna block.hotrock.name = Rocha quente block.magmarock.name = Rocha de magma @@ -793,9 +793,9 @@ block.rtg-generator.name = Gerador RTG block.spectre.name = Espectra block.meltdown.name = Derreter block.container.name = Container -block.launch-pad.name = Launch Pad -block.launch-pad.description = Launches batches of items without any need for a core launch. Unfinished. -block.launch-pad-large.name = Large Launch Pad +block.launch-pad.name = Plataforma de lançamento +block.launch-pad.description = Lança montes de itens sem qualquer necessidade de um lançamento de nucleo. Não completo. +block.launch-pad-large.name = Plataforma de lançamento grande team.blue.name = Azul team.red.name = Vermelho team.orange.name = Laranja diff --git a/core/assets/bundles/bundle_zh_TW.properties b/core/assets/bundles/bundle_zh_TW.properties index cb93cdf006..a064fd28c3 100644 --- a/core/assets/bundles/bundle_zh_TW.properties +++ b/core/assets/bundles/bundle_zh_TW.properties @@ -11,7 +11,7 @@ link.google-play.description = Google Play 商店頁面 link.wiki.description = 官方 Mindustry 維基 linkfail = 無法打開連結!\n我們已將該網址複製到您的剪貼簿。 screenshot = 截圖保存到{0} -screenshot.invalid = Map too large, potentially not enough memory for screenshot. +screenshot.invalid = 地圖太大了,可能沒有足夠的內存用於截圖。 gameover = 遊戲結束 gameover.pvp = [accent]{0}[]隊獲勝! highscore = [accent]新的高分紀錄! @@ -41,7 +41,7 @@ addplayers = 增加/移除玩家 customgame = 自訂遊戲 newgame = 新遊戲 none = 〈沒有〉 -minimap = Minimap +minimap = 小地圖 close = 關閉 quit = 退出 maps = 地圖 @@ -86,7 +86,7 @@ trace = 跟隨玩家 trace.playername = 玩家名稱:[accent]{0} trace.ip = IP:[accent]{0} trace.id = ID:[accent]{0} -trace.mobile = Mobile Client: [accent]{0} +trace.mobile = 流動客戶端:[accent]{0} trace.modclient = 自訂客戶端:[accent]{0} invalidid = 無效的客戶端 ID!請提交錯誤報告。 server.bans = 封禁 @@ -150,7 +150,7 @@ confirm = 確認 delete = 刪除 ok = 確定 open = 開啟 -customize = Customize +customize = 自訂 cancel = 取消 openlink = 開啟連結 copylink = 複製連結 @@ -167,7 +167,7 @@ loading = [accent]載入中…… saving = [accent]儲存中…… wave = [accent]第{0}波 wave.waiting = 將於{0}秒後抵達 -wave.waveInProgress = [LIGHT_GRAY]Wave in progress +wave.waveInProgress = [LIGHT_GRAY]波正在進行中 waiting = 等待中…… waiting.players = 等待玩家中…… wave.enemies = [LIGHT_GRAY]剩下{0}敵人 @@ -181,7 +181,7 @@ map.delete.confirm = 確認要刪除地圖嗎?此操作無法撤回! map.random = [accent]隨機地圖 map.nospawn = 這個地圖沒有核心!請在編輯器中添加一個[ROYAL]藍色[]的核心。 map.nospawn.pvp = 這個地圖沒有核心讓敵人重生!請在編輯器中添加一個[SCARLET]紅色[]的核心。 -map.nospawn.attack = This map does not have any enemy cores for player to attack! Add[SCARLET] red[] cores to this map in the editor. +map.nospawn.attack = 這個地圖沒有敵人核心讓可以攻擊!請在編輯器中添加一個[SCARLET]紅色[]的核心。 map.invalid = 地圖載入錯誤:地圖可能已經損壞。 editor.brush = 粉刷 editor.openin = 在編輯器中開啟 @@ -191,8 +191,8 @@ editor.mapinfo = 地圖資訊 editor.author = 作者: editor.description = 描述: editor.waves = 波次: -editor.rules = Rules: -editor.ingame = Edit In-Game +editor.rules = 規則: +editor.ingame = 在遊戲中編輯 waves.title = 波次 waves.remove = 移除 waves.never = 〈從來沒有〉 @@ -206,19 +206,19 @@ waves.edit = 編輯…… waves.copy = 複製到剪貼板 waves.load = 從剪貼板加載 waves.invalid = 剪貼板中的波次無效。 -waves.copied = 波浪已被複製。 +waves.copied = 波次已被複製。 editor.default = [LIGHT_GRAY]〈默認〉 edit = 編輯…… editor.name = 名稱: -editor.spawn = Spawn Unit -editor.removeunit = Remove Unit +editor.spawn = 重生單位 +editor.removeunit = 移除單位 editor.teams = 隊伍 editor.elevation = 高度 editor.errorload = 加載文件時出錯:\n[accent]{0} editor.errorsave = 保存文件時出錯:\n[accent]{0} -editor.errorimage = That's an image, not a map. Don't go around changing extensions expecting it to work.\n\nIf you want to import a legacy map, use the 'import legacy map' button in the editor. -editor.errorlegacy = This map is too old, and uses a legacy map format that is no longer supported. -editor.errorheader = This map file is either not valid or corrupt. +editor.errorimage = 這是一個圖像檔,而不是地圖。不要更改副檔名使它可用。\n\n如果要匯入地形圖像檔,請使用編輯器中的「匯入地形圖像檔」按鈕。 +editor.errorlegacy = 此地圖太舊,並使用不支持的舊地圖格式。 +editor.errorheader = 此地圖檔案無效或已損壞。 editor.errorname = 地圖沒有定義名稱。 editor.update = 更新 editor.randomize = 隨機化 @@ -271,8 +271,8 @@ filter.option.wall = 牆 filter.option.ore = 礦石 filter.option.floor2 = 次要地板 filter.option.threshold2 = 次要閾 -filter.option.radius = Radius -filter.option.percentile = Percentile +filter.option.radius = 半徑 +filter.option.percentile = 百分比 width = 寬度: height = 長度: menu = 主選單 @@ -292,7 +292,7 @@ abandon = 放棄 abandon.text = 此區域及其所有資源將會丟失給敵人。 locked = 鎖定 complete = [LIGHT_GRAY]完成: -zone.requirement = Wave {0} in zone {1} +zone.requirement = {0}波於區域{1} resume = 繼續區域:\n[LIGHT_GRAY]{0} bestwave = [LIGHT_GRAY]高分:{0} launch = 發射 @@ -304,7 +304,7 @@ uncover = 揭露 configure = 配置裝載 configure.locked = [LIGHT_GRAY]到達波次{0}\n以配置裝載。 zone.unlocked = [LIGHT_GRAY]{0}已解鎖。 -zone.requirement.complete = Wave {0} reached:\n{1} zone requirements met. +zone.requirement.complete = 到達波次{0}:\n滿足{1}區域要求。 zone.config.complete = 到達波次{0}:\n裝載配置已解鎖。 zone.resources = 檢測到的資源: add = 新增…… @@ -319,15 +319,15 @@ error.mapnotfound = 找不到地圖! error.io = 網絡輸入輸出錯誤。 error.any = 未知網絡錯誤。 zone.groundZero.name = 歸零地 -zone.desertWastes.name = Desert Wastes +zone.desertWastes.name = 沙漠荒原 zone.craters.name = 隕石坑 zone.frozenForest.name = 冰凍森林 -zone.ruinousShores.name = 毀滅性的海岸 +zone.ruinousShores.name = 毀滅海岸 zone.stainedMountains.name = 染山 zone.desolateRift.name = 荒涼的裂痕 zone.nuclearComplex.name = 核生產綜合體 -zone.overgrowth.name = Overgrowth -zone.tarFields.name = Tar Fields +zone.overgrowth.name = 增生 +zone.tarFields.name = 焦油田 settings.language = 語言 settings.reset = 重設為預設設定 settings.rebind = 重新綁定 @@ -346,16 +346,16 @@ no = 否 info.title = [accent]資訊 error.title = [crimson]發生錯誤 error.crashtitle = 發生錯誤 -blocks.input = Input -blocks.output = Output -blocks.booster = Booster +blocks.input = 輸入 +blocks.output = 輸出 +blocks.booster = 加速器 block.unknown = [LIGHT_GRAY]??? blocks.powercapacity = 蓄電量 blocks.powershot = 能量/射擊 blocks.targetsair = 攻擊空中目標 blocks.targetsground = 攻擊地面 blocks.itemsmoved = 移動速度 -blocks.launchtime = Time Between Launches +blocks.launchtime = 發射之間的時間 blocks.shootrange = 範圍 blocks.size = 尺寸 blocks.liquidcapacity = 液體容量 @@ -363,17 +363,17 @@ blocks.powerrange = 輸出範圍 blocks.poweruse = 能量使用 blocks.powerdamage = 能量/傷害 blocks.itemcapacity = 物品容量 -blocks.basepowergeneration = 基本能量生产 -blocks.productiontime = Production Time -blocks.repairtime = Block Full Repair Time -blocks.speedincrease = Speed Increase -blocks.range = Range +blocks.basepowergeneration = 基本能量生產 +blocks.productiontime = 生產時間 +blocks.repairtime = 方塊完全修復時間 +blocks.speedincrease = 速度提升 +blocks.range = 範圍 blocks.drilltier = 可鑽取礦物 blocks.drillspeed = 基本鑽取速度 -blocks.boosteffect = Boost Effect +blocks.boosteffect = 提升效應 blocks.maxunits = 最大活躍單位 blocks.health = 耐久度 -blocks.buildtime = Build Time +blocks.buildtime = 建設時間 blocks.inaccuracy = 誤差 blocks.shots = 射擊數 blocks.reload = 重裝彈藥 @@ -381,7 +381,7 @@ blocks.ammo = 彈藥 bar.drillspeed = 鑽頭速度:{0}/秒 bar.efficiency = 效率:{0}% bar.powerbalance = 能量變化:{0} -bar.poweramount = Power: {0} +bar.poweramount = 能量:{0} bar.poweroutput = 能量輸出:{0} bar.items = 物品:{0} bar.liquid = 液體 @@ -389,17 +389,17 @@ bar.heat = 熱 bar.power = 能量 bar.progress = 建造進度 bar.spawned = 單位:{0}/{1} -bullet.damage = [stat]{0}[lightgray] dmg -bullet.splashdamage = [stat]{0}[lightgray] area dmg ~[stat] {1}[lightgray] tiles -bullet.incendiary = [stat]incendiary -bullet.homing = [stat]homing -bullet.shock = [stat]shock -bullet.frag = [stat]frag -bullet.knockback = [stat]{0}[lightgray] knockback -bullet.freezing = [stat]freezing -bullet.tarred = [stat]tarred -bullet.multiplier = [stat]{0}[lightgray]x ammo multiplier -bullet.reload = [stat]{0}[lightgray]x reload +bullet.damage = [stat]{0}[lightgray]傷害 +bullet.splashdamage = [stat]{0}[lightgray]範圍傷害 ~[stat] {1}[lightgray]格 +bullet.incendiary = [stat]燃燒 +bullet.homing = [stat]追踪 +bullet.shock = [stat]休克 +bullet.frag = [stat]碎片 +bullet.knockback = [stat]{0}[lightgray]擊退 +bullet.freezing = [stat]冷凍 +bullet.tarred = [stat]焦油 +bullet.multiplier = [stat]{0}[lightgray]×彈藥倍數 +bullet.reload = [stat]{0}[lightgray]×重裝 unit.blocks = 方塊 unit.powersecond = 能量單位/秒 unit.liquidsecond = 液體單位/秒 @@ -408,8 +408,8 @@ unit.liquidunits = 液體單位 unit.powerunits = 能量單位 unit.degrees = 度 unit.seconds = 秒 -unit.persecond = /sec -unit.timesspeed = x speed +unit.persecond = /秒 +unit.timesspeed = ×速度 unit.percent = % unit.items = 物品 category.general = 一般 @@ -419,11 +419,11 @@ category.items = 物品 category.crafting = 合成 category.shooting = 射擊 category.optional = 可選的強化 -setting.landscape.name = Lock Landscape -setting.shadows.name = Shadows -setting.linear.name = Linear Filtering +setting.landscape.name = 鎖定景觀 +setting.shadows.name = 陰影 +setting.linear.name = 線性過濾 setting.animatedwater.name = 動畫水 -setting.animatedshields.name = Animated Shields +setting.animatedshields.name = 動畫力牆 setting.antialias.name = 消除鋸齒[LIGHT_GRAY](需要重啟)[] setting.indicators.name = 盟友指標 setting.autotarget.name = 自動射擊 @@ -443,19 +443,19 @@ setting.sensitivity.name = 控制器靈敏度 setting.saveinterval.name = 自動存檔間隔 setting.seconds = {0}秒 setting.fullscreen.name = 全螢幕 -setting.borderlesswindow.name = Borderless Window[LIGHT_GRAY] (may require restart) +setting.borderlesswindow.name = 無邊框窗口[LIGHT_GRAY](可能需要重啟) setting.fps.name = 顯示FPS setting.vsync.name = 垂直同步 setting.lasers.name = 顯示雷射光束 -setting.pixelate.name = Pixelate [LIGHT_GRAY](may decrease performance) +setting.pixelate.name = 像素化[LIGHT_GRAY](可能降低性能) setting.minimap.name = 顯示小地圖 setting.musicvol.name = 音樂音量 setting.mutemusic.name = 靜音 setting.sfxvol.name = 音效音量 setting.mutesound.name = 靜音 setting.crashreport.name = 發送匿名崩潰報告 -setting.chatopacity.name = Chat Opacity -setting.playerchat.name = Display In-Game Chat +setting.chatopacity.name = 聊天框不透明度 +setting.playerchat.name = 在遊戲中顯示聊天框 keybind.title = 重新綁定按鍵 category.general.name = 一般 category.view.name = 查看 @@ -480,7 +480,7 @@ keybind.zoom_hold.name = 按住縮放 keybind.zoom.name = 縮放 keybind.menu.name = 主選單 keybind.pause.name = 暫停遊戲 -keybind.minimap.name = Minimap +keybind.minimap.name = 小地圖 keybind.dash.name = 衝刺 keybind.chat.name = 聊天 keybind.player_list.name = 玩家列表 @@ -501,32 +501,32 @@ mode.pvp.name = 對戰 mode.pvp.description = 和其他玩家鬥爭。 mode.attack.name = 攻擊 mode.attack.description = 沒有波次,目標是摧毀敵人的基地。 -mode.custom = Custom Rules -rules.infiniteresources = Infinite Resources -rules.wavetimer = Wave Timer -rules.waves = Waves -rules.enemyCheat = Infinite AI Resources -rules.unitdrops = Unit Drops -rules.unitbuildspeedmultiplier = Unit Creation Speed Multiplier -rules.unithealthmultiplier = Unit Health Multiplier -rules.playerhealthmultiplier = Player Health Multiplier -rules.playerdamagemultiplier = Player Damage Multiplier -rules.unitdamagemultiplier = Unit Damage Multiplier -rules.enemycorebuildradius = Enemy Core No-Build Radius:[LIGHT_GRAY] (tiles) -rules.respawntime = Respawn Time:[LIGHT_GRAY] (sec) -rules.wavespacing = Wave Spacing:[LIGHT_GRAY] (sec) -rules.buildcostmultiplier = Build Cost Multiplier -rules.buildspeedmultiplier = Build Speed Multiplier -rules.waitForWaveToEnd = Waves wait for enemies -rules.dropzoneradius = Drop Zone Radius:[LIGHT_GRAY] (tiles) -rules.respawns = Max respawns per wave -rules.limitedRespawns = Limit Respawns -rules.title.waves = Waves -rules.title.respawns = Respawns -rules.title.resourcesbuilding = Resources & Building -rules.title.player = Players -rules.title.enemy = Enemies -rules.title.unit = Units +mode.custom = 自訂規則 +rules.infiniteresources = 無限資源 +rules.wavetimer = 波次時間 +rules.waves = 波次 +rules.enemyCheat = 電腦無限資源 +rules.unitdrops = 單位掉落 +rules.unitbuildspeedmultiplier = 單位建設速度倍數 +rules.unithealthmultiplier = 單位耐久度倍數 +rules.playerhealthmultiplier = 玩家耐久度倍數 +rules.playerdamagemultiplier = 玩家傷害倍數 +rules.unitdamagemultiplier = 單位傷害倍數 +rules.enemycorebuildradius = 敵人核心無建設半徑︰[LIGHT_GRAY](格) +rules.respawntime = 重生時間︰[LIGHT_GRAY](秒) +rules.wavespacing = 波次間距︰[LIGHT_GRAY](秒) +rules.buildcostmultiplier = 建設成本倍數 +rules.buildspeedmultiplier = 建設速度倍數 +rules.waitForWaveToEnd = 等待所有敵人毀滅才開始波次 +rules.dropzoneradius = 掉落區半徑:[LIGHT_GRAY](格) +rules.respawns = 每波次最多重生次數 +rules.limitedRespawns = 限制重生 +rules.title.waves = 波次 +rules.title.respawns = 重生 +rules.title.resourcesbuilding = 資源與建築 +rules.title.player = 玩家 +rules.title.enemy = 敵人 +rules.title.unit = 單位 content.item.name = 物品 content.liquid.name = 液體 content.unit.name = 機組 @@ -536,7 +536,7 @@ item.copper.name = 銅 item.copper.description = 一種有用的結構材料。在各種類型的方塊中廣泛使用。 item.lead.name = 鉛 item.lead.description = 一種基本的起始材料。被廣泛用於電子設備和運輸液體方塊。 -item.coal.name = 煤 +item.coal.name = 煤炭 item.coal.description = 一種常見並容易獲得的燃料。 item.graphite.name = 石墨 item.titanium.name = 鈦 @@ -575,7 +575,7 @@ mech.delta-mech.name = 德爾塔 mech.delta-mech.weapon = 電弧生成機 mech.delta-mech.ability = 放電 mech.delta-mech.description = 一种快速、轻铠的机甲,是用於打了就跑的攻擊。对结构造成的伤害很小,但可以用弧形闪电武器很快杀死大量敌方机组。 -mech.tau-mech.name = Tau機甲 +mech.tau-mech.name = 牛頭機甲 mech.tau-mech.weapon = 重構激光 mech.tau-mech.ability = 修复陣 mech.tau-mech.description = 支援機甲。射擊友好方塊以治療它們。可以使用它的修復能力熄滅火焰並治療一定範圍內的友軍。 @@ -613,9 +613,9 @@ liquid.viscosity = [LIGHT_GRAY]粘性:{0} liquid.temperature = [LIGHT_GRAY]温度:{0} block.grass.name = 草 block.salt.name = 鹽 -block.saltrocks.name = Salt Rocks -block.pebbles.name = Pebbles -block.tendrils.name = Tendrils +block.saltrocks.name = 鹽岩 +block.pebbles.name = 卵石 +block.tendrils.name = 卷鬚 block.sandrocks.name = 沙岩 block.spore-pine.name = 孢子鬆 block.sporerocks.name = 孢子岩 @@ -624,7 +624,7 @@ block.snowrock.name = 雪巖 block.shale.name = 頁岩 block.shale-boulder.name = 頁岩巨石 block.moss.name = 苔蘚 -block.shrubs.name = Shrubs +block.shrubs.name = 灌木 block.spore-moss.name = 孢子苔蘚 block.shalerocks.name = 頁岩岩石 block.scrap-wall.name = 廢牆 @@ -662,21 +662,21 @@ block.icerocks.name = 冰岩 block.snowrocks.name = 雪巖 block.dunerocks.name = 沙丘岩 block.pine.name = 松樹 -block.white-tree-dead.name = 白樹死了 +block.white-tree-dead.name = 死了的白樹 block.white-tree.name = 白樹 block.spore-cluster.name = 孢子簇 block.metal-floor.name = 金屬地板 -block.metal-floor-2.name = 金屬地板二 -block.metal-floor-3.name = 金屬地板三 -block.metal-floor-5.name = 金屬地板五 -block.metal-floor-damaged.name = 金屬地板損壞 -block.dark-panel-1.name = Dark Panel 1 -block.dark-panel-2.name = Dark Panel 2 -block.dark-panel-3.name = Dark Panel 3 -block.dark-panel-4.name = Dark Panel 4 -block.dark-panel-5.name = Dark Panel 5 -block.dark-panel-6.name = Dark Panel 6 -block.dark-metal.name = Dark Metal +block.metal-floor-2.name = 金屬地板 2 +block.metal-floor-3.name = 金屬地板 3 +block.metal-floor-5.name = 金屬地板 5 +block.metal-floor-damaged.name = 損壞的金屬地板 +block.dark-panel-1.name = 黑面板 1 +block.dark-panel-2.name = 黑面板 2 +block.dark-panel-3.name = 黑面板 3 +block.dark-panel-4.name = 黑面板 4 +block.dark-panel-5.name = 黑面板 5 +block.dark-panel-6.name = 黑面板 6 +block.dark-metal.name = 黑金屬 block.ignarock.name = 火成岩 block.hotrock.name = 熱岩 block.magmarock.name = 岩漿岩 @@ -713,7 +713,7 @@ block.melter.name = 熔爐 block.incinerator.name = 焚化爐 block.spore-press.name = 孢子壓縮機 block.separator.name = 分離機 -block.coal-centrifuge.name = Coal Centrifuge +block.coal-centrifuge.name = 煤炭離心機 block.power-node.name = 能量節點 block.power-node-large.name = 大型能量節點 block.surge-tower.name = 波動塔 @@ -728,13 +728,13 @@ block.pneumatic-drill.name = 氣動鑽頭 block.laser-drill.name = 激光鑽頭 block.water-extractor.name = 水提取器 block.cultivator.name = 耕種機 -block.dart-mech-pad.name = Dart Mech Pad +block.dart-mech-pad.name = 鏢船機甲墊 block.delta-mech-pad.name = 德爾塔機甲墊 block.javelin-ship-pad.name = 標槍機甲墊 block.trident-ship-pad.name = 三叉船墊 block.glaive-ship-pad.name = 長柄船墊 block.omega-mech-pad.name = 奧米伽機甲墊 -block.tau-mech-pad.name = Tau機甲墊 +block.tau-mech-pad.name = 牛頭機甲墊 block.conduit.name = 管線 block.mechanical-pump.name = 機械泵 block.item-source.name = 物品源 @@ -779,7 +779,7 @@ block.blast-drill.name = 爆破鑽頭 block.thermal-pump.name = 熱能泵 block.thermal-generator.name = 熱能發電機 block.alloy-smelter.name = 合金冶煉廠 -block.mender.name = Mender +block.mender.name = 修理方塊 block.mend-projector.name = 修理投影器 block.surge-wall.name = 波動牆 block.surge-wall-large.name = 大型波動牆 @@ -795,7 +795,7 @@ block.meltdown.name = 熔毀炮 block.container.name = 容器 block.launch-pad.name = 發射台 block.launch-pad.description = 無需從核心發射即可發射物品。未完成。 -block.launch-pad-large.name = Large Launch Pad +block.launch-pad-large.name = 大型發射台 team.blue.name = 藍 team.red.name = 紅 team.orange.name = 橙 diff --git a/core/assets/contributors b/core/assets/contributors index 7b5fb43f46..42bea20654 100644 --- a/core/assets/contributors +++ b/core/assets/contributors @@ -21,7 +21,6 @@ Sonnicon CinExPL toushangyouxiang xgamezs -Skybbles // L5474 William So beito BeefEX @@ -61,7 +60,6 @@ player20033 Ignacy J-VdS Kenny -L5474 Franciszek Zaranowicz Andreas Heiskanen Doyoung Gwak @@ -70,4 +68,5 @@ Math2128 Michael Plotke Niko Paul T -Dominik \ No newline at end of file +Dominik +Arkanic \ No newline at end of file diff --git a/core/assets/cursors/cursor.png b/core/assets/cursors/cursor.png index d8487b7fa1..86f4632037 100644 Binary files a/core/assets/cursors/cursor.png and b/core/assets/cursors/cursor.png differ diff --git a/core/assets/sprites/icon.icns b/core/assets/icons/icon.icns similarity index 100% rename from core/assets/sprites/icon.icns rename to core/assets/icons/icon.icns diff --git a/core/assets/icons/icon.ico b/core/assets/icons/icon.ico new file mode 100644 index 0000000000..20d4a3e150 Binary files /dev/null and b/core/assets/icons/icon.ico differ diff --git a/core/assets/sprites/icon.png b/core/assets/icons/icon.png similarity index 100% rename from core/assets/sprites/icon.png rename to core/assets/icons/icon.png diff --git a/core/assets/sprites/icon@2x.icns b/core/assets/icons/icon@2x.icns similarity index 100% rename from core/assets/sprites/icon@2x.icns rename to core/assets/icons/icon@2x.icns diff --git a/core/assets/sprites/icon_64.png b/core/assets/icons/icon_64.png similarity index 100% rename from core/assets/sprites/icon_64.png rename to core/assets/icons/icon_64.png diff --git a/core/assets/maps/caldera.msav b/core/assets/maps/caldera.msav new file mode 100644 index 0000000000..4ed0889f5e Binary files /dev/null and b/core/assets/maps/caldera.msav differ diff --git a/core/assets/maps/canyon.msav b/core/assets/maps/canyon.msav new file mode 100644 index 0000000000..06f5b6e064 Binary files /dev/null and b/core/assets/maps/canyon.msav differ diff --git a/core/assets/maps/crags.msav b/core/assets/maps/crags.msav new file mode 100644 index 0000000000..1fb64c01e7 Binary files /dev/null and b/core/assets/maps/crags.msav differ diff --git a/core/assets/maps/craters.msav b/core/assets/maps/craters.msav index 91066fd661..14f91c18ca 100644 Binary files a/core/assets/maps/craters.msav and b/core/assets/maps/craters.msav differ diff --git a/core/assets/maps/desolateRift.msav b/core/assets/maps/desolateRift.msav index 67a0528236..e1f7fe3394 100644 Binary files a/core/assets/maps/desolateRift.msav and b/core/assets/maps/desolateRift.msav differ diff --git a/core/assets/maps/fork.msav b/core/assets/maps/fork.msav new file mode 100644 index 0000000000..0a6a82d226 Binary files /dev/null and b/core/assets/maps/fork.msav differ diff --git a/core/assets/maps/fortress.msav b/core/assets/maps/fortress.msav index fdfa666271..25f2c10835 100644 Binary files a/core/assets/maps/fortress.msav and b/core/assets/maps/fortress.msav differ diff --git a/core/assets/maps/frozenForest.msav b/core/assets/maps/frozenForest.msav index 3984aeebc8..8e6ab8fdc9 100644 Binary files a/core/assets/maps/frozenForest.msav and b/core/assets/maps/frozenForest.msav differ diff --git a/core/assets/maps/glacier.msav b/core/assets/maps/glacier.msav new file mode 100644 index 0000000000..12c693556a Binary files /dev/null and b/core/assets/maps/glacier.msav differ diff --git a/core/assets/maps/groundZero.msav b/core/assets/maps/groundZero.msav index dbecd18706..73e52f5b18 100644 Binary files a/core/assets/maps/groundZero.msav and b/core/assets/maps/groundZero.msav differ diff --git a/core/assets/maps/impact0078.msav b/core/assets/maps/impact0078.msav index 92afbebb7b..03bcfe8be2 100644 Binary files a/core/assets/maps/impact0078.msav and b/core/assets/maps/impact0078.msav differ diff --git a/core/assets/maps/islands.msav b/core/assets/maps/islands.msav index ce9a3baedc..66ad2aa646 100644 Binary files a/core/assets/maps/islands.msav and b/core/assets/maps/islands.msav differ diff --git a/core/assets/maps/labyrinth.msav b/core/assets/maps/labyrinth.msav index e1d51492aa..7501a592ad 100644 Binary files a/core/assets/maps/labyrinth.msav and b/core/assets/maps/labyrinth.msav differ diff --git a/core/assets/maps/maze.msav b/core/assets/maps/maze.msav index 775b9c83cf..edcf158f33 100644 Binary files a/core/assets/maps/maze.msav and b/core/assets/maps/maze.msav differ diff --git a/core/assets/maps/nuclearProductionComplex.msav b/core/assets/maps/nuclearProductionComplex.msav index 02a86783c1..5a48206817 100644 Binary files a/core/assets/maps/nuclearProductionComplex.msav and b/core/assets/maps/nuclearProductionComplex.msav differ diff --git a/core/assets/maps/overgrowth.msav b/core/assets/maps/overgrowth.msav index 58135743ed..2c3316bd81 100644 Binary files a/core/assets/maps/overgrowth.msav and b/core/assets/maps/overgrowth.msav differ diff --git a/core/assets/maps/ruinousShores.msav b/core/assets/maps/ruinousShores.msav index 1f3a1628bd..36ec4cc868 100644 Binary files a/core/assets/maps/ruinousShores.msav and b/core/assets/maps/ruinousShores.msav differ diff --git a/core/assets/maps/saltFlats.msav b/core/assets/maps/saltFlats.msav new file mode 100644 index 0000000000..4d63be50cd Binary files /dev/null and b/core/assets/maps/saltFlats.msav differ diff --git a/core/assets/maps/saltcrags.msav b/core/assets/maps/saltcrags.msav deleted file mode 100644 index 406168ec90..0000000000 Binary files a/core/assets/maps/saltcrags.msav and /dev/null differ diff --git a/core/assets/maps/shattered.msav b/core/assets/maps/shattered.msav new file mode 100644 index 0000000000..cad5016e9d Binary files /dev/null and b/core/assets/maps/shattered.msav differ diff --git a/core/assets/maps/stainedMountains.msav b/core/assets/maps/stainedMountains.msav index 6312b102cb..5cd9828d85 100644 Binary files a/core/assets/maps/stainedMountains.msav and b/core/assets/maps/stainedMountains.msav differ diff --git a/core/assets/maps/tarFields.msav b/core/assets/maps/tarFields.msav index b3910d34ce..8976acc148 100644 Binary files a/core/assets/maps/tarFields.msav and b/core/assets/maps/tarFields.msav differ diff --git a/core/assets/maps/tendrils.msav b/core/assets/maps/tendrils.msav new file mode 100644 index 0000000000..178c11a03e Binary files /dev/null and b/core/assets/maps/tendrils.msav differ diff --git a/core/assets/maps/triad.msav b/core/assets/maps/triad.msav new file mode 100644 index 0000000000..a693b02cba Binary files /dev/null and b/core/assets/maps/triad.msav differ diff --git a/core/assets/maps/veins.msav b/core/assets/maps/veins.msav new file mode 100644 index 0000000000..d63dc2c1e8 Binary files /dev/null and b/core/assets/maps/veins.msav differ diff --git a/core/assets/maps/wasteland.msav b/core/assets/maps/wasteland.msav new file mode 100644 index 0000000000..f7bb73595e Binary files /dev/null and b/core/assets/maps/wasteland.msav differ diff --git a/core/assets/shaders/unitbuild.fragment.glsl b/core/assets/shaders/unitbuild.fragment.glsl index fe1b07ea42..eff888a827 100644 --- a/core/assets/shaders/unitbuild.fragment.glsl +++ b/core/assets/shaders/unitbuild.fragment.glsl @@ -43,9 +43,11 @@ void main() { vec4 c = texture2D(u_texture, v_texCoord.xy); if(1.0-abs(coords.x - 0.5)*2.0 < 1.0-u_progress){ - c = vec4(0.0); + // c = vec4(0.0); } + c.a *= u_progress; + if(c.a > 0.01){ float f = abs(sin(coords.x*2.0 + u_time)); if(f > 0.9) diff --git a/core/assets/sprites/backgrounds/planet-zero.png b/core/assets/sprites/backgrounds/planet-zero.png new file mode 100644 index 0000000000..b1e13f744c Binary files /dev/null and b/core/assets/sprites/backgrounds/planet-zero.png differ diff --git a/core/assets/sprites/backgrounds/stars.png b/core/assets/sprites/backgrounds/stars.png new file mode 100644 index 0000000000..41a8fadb7b Binary files /dev/null and b/core/assets/sprites/backgrounds/stars.png differ diff --git a/core/assets/sprites/block_colors.png b/core/assets/sprites/block_colors.png index abf8ce2704..2f74fd7633 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/logo.png b/core/assets/sprites/logo.png new file mode 100644 index 0000000000..eee1e0e658 Binary files /dev/null and b/core/assets/sprites/logo.png differ diff --git a/core/assets/sprites/sprites.atlas b/core/assets/sprites/sprites.atlas index 9b6089baec..c2eb5af812 100644 --- a/core/assets/sprites/sprites.atlas +++ b/core/assets/sprites/sprites.atlas @@ -6,8402 +6,5173 @@ filter: Nearest,Nearest repeat: none force-projector rotate: false - xy: 709, 1431 + xy: 521, 480 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +force-projector-icon-full + rotate: false + xy: 521, 480 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 force-projector-top rotate: false - xy: 302, 1302 + xy: 489, 382 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 mend-projector rotate: false - xy: 1897, 1069 + xy: 1544, 1597 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +mend-projector-icon-full + rotate: false + xy: 1544, 1597 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 mend-projector-top rotate: false - xy: 1963, 1057 + xy: 1610, 1597 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 mender rotate: false - xy: 1229, 400 + xy: 1307, 1057 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +mender-icon-full + rotate: false + xy: 1307, 1057 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 mender-top rotate: false - xy: 1229, 366 + xy: 1341, 1091 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 overdrive-projector rotate: false - xy: 924, 1073 + xy: 1742, 1593 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +overdrive-projector-icon-full + rotate: false + xy: 1742, 1593 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 overdrive-projector-top rotate: false - xy: 990, 1073 + xy: 1808, 1593 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 shock-mine rotate: false - xy: 567, 31 + xy: 1341, 717 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +bridge-arrow + rotate: false + xy: 1763, 1319 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conveyor rotate: false - xy: 1191, 253 + xy: 1113, 86 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +bridge-conveyor-icon-full + rotate: false + xy: 1113, 86 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conveyor-bridge rotate: false - xy: 1267, 874 + xy: 1113, 52 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conveyor-end rotate: false - xy: 1267, 840 + xy: 1113, 18 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 center rotate: false - xy: 1267, 806 + xy: 1545, 1215 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-0-0 rotate: false - xy: 1601, 927 + xy: 1137, 1033 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conveyor-icon-full + rotate: false + xy: 1137, 1033 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-0-1 rotate: false - xy: 1431, 912 + xy: 1137, 999 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-0-2 rotate: false - xy: 1465, 912 + xy: 1137, 965 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-0-3 rotate: false - xy: 1499, 893 + xy: 1137, 931 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-1-0 rotate: false - xy: 1533, 893 + xy: 1137, 897 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-1-1 rotate: false - xy: 1567, 893 + xy: 1137, 863 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-1-2 rotate: false - xy: 1601, 893 + xy: 1137, 829 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-1-3 rotate: false - xy: 1635, 903 + xy: 1137, 795 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-2-0 rotate: false - xy: 1669, 903 + xy: 1137, 761 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-2-1 rotate: false - xy: 1703, 903 + xy: 1137, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-2-2 rotate: false - xy: 1737, 903 + xy: 1137, 693 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-2-3 rotate: false - xy: 1771, 903 + xy: 2006, 1625 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-3-0 rotate: false - xy: 1805, 903 + xy: 2006, 1591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-3-1 rotate: false - xy: 1839, 903 + xy: 2006, 1557 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-3-2 rotate: false - xy: 1873, 903 + xy: 2006, 1523 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-3-3 rotate: false - xy: 1907, 891 + xy: 2006, 1489 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-4-0 rotate: false - xy: 1941, 891 + xy: 1133, 659 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-4-1 rotate: false - xy: 1975, 891 + xy: 1133, 625 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-4-2 rotate: false - xy: 2009, 891 + xy: 1133, 591 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conveyor-4-3 rotate: false - xy: 1301, 860 + xy: 1133, 557 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-0-0 rotate: false - xy: 737, 227 + xy: 1235, 615 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium-conveyor-icon-full + rotate: false + xy: 1235, 615 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-0-1 rotate: false - xy: 669, 125 + xy: 1269, 649 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-0-2 rotate: false - xy: 703, 159 + xy: 1235, 581 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-0-3 rotate: false - xy: 737, 193 + xy: 1269, 615 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-1-0 rotate: false - xy: 669, 91 + xy: 1303, 649 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-1-1 rotate: false - xy: 703, 125 + xy: 1269, 581 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-1-2 rotate: false - xy: 737, 159 + xy: 1303, 615 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-1-3 rotate: false - xy: 669, 57 + xy: 1337, 649 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-2-0 rotate: false - xy: 703, 91 + xy: 1303, 581 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-2-1 rotate: false - xy: 737, 125 + xy: 1337, 615 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-2-2 rotate: false - xy: 669, 23 + xy: 1371, 649 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-2-3 rotate: false - xy: 703, 57 + xy: 1337, 581 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-3-0 rotate: false - xy: 737, 91 + xy: 1371, 615 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-3-1 rotate: false - xy: 703, 23 + xy: 1371, 581 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-3-2 rotate: false - xy: 737, 57 + xy: 1167, 547 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-3-3 rotate: false - xy: 737, 23 + xy: 1201, 547 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-4-0 rotate: false - xy: 771, 251 + xy: 1235, 547 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-4-1 rotate: false - xy: 805, 251 + xy: 1269, 547 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-4-2 rotate: false - xy: 771, 217 + xy: 1303, 547 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-conveyor-4-3 rotate: false - xy: 771, 183 + xy: 1337, 547 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 distributor rotate: false - xy: 924, 1139 + xy: 459, 120 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +distributor-icon-full + rotate: false + xy: 459, 120 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 junction rotate: false - xy: 1437, 640 + xy: 1239, 1091 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +junction-icon-full + rotate: false + xy: 1239, 1091 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 mass-driver-base rotate: false - xy: 1101, 1337 + xy: 651, 752 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 overflow-gate rotate: false - xy: 1297, 350 + xy: 1341, 1023 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +overflow-gate-icon-full + rotate: false + xy: 1341, 1023 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conveyor rotate: false - xy: 1365, 350 + xy: 1307, 955 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-conveyor-icon-full + rotate: false + xy: 1307, 955 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conveyor-arrow rotate: false - xy: 1365, 316 + xy: 1341, 989 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conveyor-bridge rotate: false - xy: 1403, 391 + xy: 1375, 1023 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conveyor-end rotate: false - xy: 1399, 357 + xy: 1171, 785 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 router rotate: false - xy: 567, 337 + xy: 1205, 717 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +router-icon-full + rotate: false + xy: 1205, 717 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 sorter rotate: false - xy: 635, 219 + xy: 1307, 683 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sorter-icon-full + rotate: false + xy: 1307, 683 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 blast-drill rotate: false - xy: 1360, 1919 + xy: 1804, 1919 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 blast-drill-rim rotate: false - xy: 1620, 1919 + xy: 526, 1597 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 blast-drill-rotator rotate: false - xy: 1750, 1919 + xy: 453, 1394 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 blast-drill-top rotate: false - xy: 1880, 1919 + xy: 163, 1033 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 laser-drill rotate: false - xy: 694, 1235 + xy: 685, 186 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 laser-drill-rim rotate: false - xy: 596, 1137 + xy: 583, 1438 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 laser-drill-rotator rotate: false - xy: 694, 1137 + xy: 681, 1438 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 laser-drill-top rotate: false - xy: 807, 1435 + xy: 609, 1340 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 mechanical-drill rotate: false - xy: 1386, 1103 + xy: 1412, 1625 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 mechanical-drill-rotator rotate: false - xy: 1765, 1069 + xy: 1412, 1559 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 mechanical-drill-top rotate: false - xy: 1831, 1069 + xy: 1478, 1597 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 oil-extractor rotate: false - xy: 1297, 1447 + xy: 749, 1144 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 oil-extractor-liquid rotate: false - xy: 1395, 1463 + xy: 749, 948 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 oil-extractor-rotator rotate: false - xy: 1395, 1365 + xy: 749, 850 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 oil-extractor-top rotate: false - xy: 1493, 1463 + xy: 749, 752 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 pneumatic-drill rotate: false - xy: 1584, 1061 + xy: 1940, 1527 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 pneumatic-drill-rotator rotate: false - xy: 1584, 995 + xy: 1214, 1493 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 pneumatic-drill-top rotate: false - xy: 1650, 1003 + xy: 1280, 1493 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 water-extractor rotate: false - xy: 425, 1072 + xy: 913, 891 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 water-extractor-liquid rotate: false - xy: 425, 940 + xy: 913, 825 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 water-extractor-rotator rotate: false - xy: 425, 874 + xy: 979, 825 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 water-extractor-top rotate: false - xy: 425, 808 + xy: 913, 759 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-border rotate: false - xy: 1233, 672 + xy: 1943, 1361 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-middle rotate: false - xy: 1233, 638 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -pump-liquid - rotate: false - xy: 1233, 638 + xy: 1695, 1315 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-select rotate: false - xy: 1233, 604 + xy: 1729, 1319 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-liquid rotate: false - xy: 1431, 946 + xy: 1103, 829 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 place-arrow rotate: false - xy: 1591, 1463 + xy: 717, 556 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 rubble-1-0 rotate: false - xy: 1716, 937 + xy: 1610, 1465 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 rubble-1-1 rotate: false - xy: 1782, 937 + xy: 1676, 1465 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 rubble-2-0 rotate: false - xy: 1848, 937 + xy: 1742, 1461 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 rubble-2-1 rotate: false - xy: 1914, 991 + xy: 1808, 1461 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 rubble-3-0 rotate: false - xy: 1787, 1463 + xy: 783, 262 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 rubble-3-1 rotate: false - xy: 1787, 1463 + xy: 783, 262 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 rubble-4-0 rotate: false - xy: 1655, 1659 + xy: 293, 744 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 rubble-4-1 rotate: false - xy: 1655, 1659 + xy: 293, 744 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 bridge-conduit rotate: false - xy: 1233, 570 + xy: 1797, 1323 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +bridge-conduit-icon-full + rotate: false + xy: 1797, 1323 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conduit-arrow rotate: false - xy: 1233, 536 + xy: 1831, 1323 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conveyor-arrow rotate: false - xy: 1233, 536 + xy: 1831, 1323 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conduit-bridge rotate: false - xy: 1233, 502 + xy: 1865, 1323 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conduit-end rotate: false - xy: 1233, 468 + xy: 1113, 120 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom rotate: false - xy: 1267, 466 + xy: 1103, 1033 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-0 rotate: false - xy: 1363, 1003 + xy: 1103, 999 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-1 rotate: false - xy: 1397, 1003 + xy: 1103, 965 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-2 rotate: false - xy: 1363, 969 + xy: 1103, 931 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-3 rotate: false - xy: 1363, 935 + xy: 1103, 931 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-4 rotate: false - xy: 1397, 969 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conduit-bottom-5 - rotate: false - xy: 1397, 935 + xy: 1103, 931 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-bottom-6 rotate: false - xy: 1431, 980 + xy: 1103, 931 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conduit-bottom-5 + rotate: false + xy: 1103, 897 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-top-0 rotate: false - xy: 1465, 946 + xy: 1103, 795 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-top-1 rotate: false - xy: 1499, 961 + xy: 1103, 761 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-top-2 rotate: false - xy: 1533, 961 + xy: 1103, 727 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-top-3 rotate: false - xy: 1567, 961 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conduit-top-4 - rotate: false - xy: 1601, 961 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conduit-top-5 - rotate: false - xy: 1499, 927 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conduit-top-6 - rotate: false - xy: 1533, 927 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -liquid-junction - rotate: false - xy: 1403, 425 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -liquid-router-bottom - rotate: false - xy: 1635, 869 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -liquid-router-liquid - rotate: false - xy: 1703, 869 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -liquid-router-top - rotate: false - xy: 1737, 869 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -liquid-tank-bottom - rotate: false - xy: 905, 1435 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -liquid-tank-liquid - rotate: false - xy: 1003, 1435 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -liquid-tank-top - rotate: false - xy: 1003, 1337 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -mechanical-pump - rotate: false - xy: 1975, 857 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -phase-conduit - rotate: false - xy: 1297, 316 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -phase-conduit-arrow - rotate: false - xy: 1331, 350 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -phase-conduit-bridge - rotate: false - xy: 1365, 384 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -phase-conduit-end - rotate: false - xy: 1331, 316 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -pulse-conduit-top-0 - rotate: false - xy: 1437, 368 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -pulse-conduit-top-1 - rotate: false - xy: 1433, 334 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -pulse-conduit-top-2 - rotate: false - xy: 1433, 300 + xy: 1103, 693 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-3 rotate: false - xy: 1433, 266 + xy: 1103, 693 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conduit-top-4 + rotate: false + xy: 1144, 1135 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conduit-top-5 + rotate: false + xy: 1137, 1101 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conduit-top-6 + rotate: false + xy: 1137, 1067 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-junction + rotate: false + xy: 1205, 1023 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-junction-icon-full + rotate: false + xy: 1205, 1023 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-router-bottom + rotate: false + xy: 1273, 1091 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-router-liquid + rotate: false + xy: 1205, 989 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-router-top + rotate: false + xy: 1239, 1023 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-tank-bottom + rotate: false + xy: 651, 1242 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +liquid-tank-liquid + rotate: false + xy: 651, 1046 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +liquid-tank-top + rotate: false + xy: 651, 948 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +mechanical-pump + rotate: false + xy: 1239, 989 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +mechanical-pump-icon-full + rotate: false + xy: 1239, 989 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-conduit + rotate: false + xy: 1171, 819 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-conduit-icon-full + rotate: false + xy: 1171, 819 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-conduit-arrow + rotate: false + xy: 1205, 853 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-conduit-bridge + rotate: false + xy: 1239, 887 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-conduit-end + rotate: false + xy: 1273, 921 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pulse-conduit-top-0 + rotate: false + xy: 1171, 751 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pulse-conduit-top-1 + rotate: false + xy: 1205, 785 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pulse-conduit-top-2 + rotate: false + xy: 1239, 819 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-4 rotate: false - xy: 1433, 232 + xy: 1273, 853 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-5 rotate: false - xy: 1399, 221 + xy: 1307, 887 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-top-6 rotate: false - xy: 1433, 198 + xy: 1341, 921 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 rotary-pump rotate: false - xy: 1848, 1003 + xy: 1478, 1465 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +rotary-pump-icon-full + rotate: false + xy: 1478, 1465 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 thermal-pump rotate: false - xy: 1493, 1267 + xy: 881, 164 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +thermal-pump-icon-full + rotate: false + xy: 881, 164 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 dart-mech-pad rotate: false - xy: 924, 1205 + xy: 1009, 1485 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +dart-mech-pad-icon-full + rotate: false + xy: 1009, 1485 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 delta-mech-pad rotate: false - xy: 990, 1271 + xy: 393, 60 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +delta-mech-pad-icon-full + rotate: false + xy: 393, 60 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 glaive-ship-pad rotate: false - xy: 596, 1235 + xy: 685, 284 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +glaive-ship-pad-icon-full + rotate: false + xy: 685, 284 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 javelin-ship-pad rotate: false - xy: 1188, 1205 + xy: 1214, 1625 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +javelin-ship-pad-icon-full + rotate: false + xy: 1214, 1625 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 omega-mech-pad rotate: false - xy: 1493, 1365 + xy: 749, 654 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +omega-mech-pad-icon-full + rotate: false + xy: 749, 654 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 tau-mech-pad rotate: false - xy: 359, 412 + xy: 1035, 1353 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +tau-mech-pad-icon-full + rotate: false + xy: 1035, 1353 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 trident-ship-pad rotate: false - xy: 359, 214 + xy: 979, 1155 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +trident-ship-pad-icon-full + rotate: false + xy: 979, 1155 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 battery rotate: false - xy: 1233, 842 + xy: 797, 1738 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +battery-icon-full + rotate: false + xy: 797, 1738 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 battery-large rotate: false - xy: 219, 1443 + xy: 293, 386 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +battery-large-icon-full + rotate: false + xy: 293, 386 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 combustion-generator rotate: false - xy: 1267, 534 + xy: 1103, 1101 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +combustion-generator-icon-full + rotate: false + xy: 1103, 1101 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 combustion-generator-top rotate: false - xy: 1267, 500 + xy: 1103, 1067 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 differential-generator rotate: false - xy: 513, 1431 + xy: 656, 1536 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +differential-generator-icon-full + rotate: false + xy: 656, 1536 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +differential-generator-liquid + rotate: false + xy: 293, 190 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 differential-generator-top rotate: false - xy: 611, 1431 + xy: 391, 386 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 impact-reactor rotate: false - xy: 163, 1064 + xy: 1888, 1789 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 impact-reactor-bottom rotate: false - xy: 163, 934 + xy: 1498, 1663 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 impact-reactor-light rotate: false - xy: 163, 674 + xy: 1758, 1659 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 impact-reactor-plasma-0 rotate: false - xy: 163, 544 + xy: 1888, 1659 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 impact-reactor-plasma-1 rotate: false - xy: 163, 414 + xy: 163, 253 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 impact-reactor-plasma-2 rotate: false - xy: 163, 284 + xy: 155, 123 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 impact-reactor-plasma-3 rotate: false - xy: 163, 154 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -impact-reactor-top - rotate: false - xy: 163, 24 + xy: 219, 1264 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 power-node rotate: false - xy: 1263, 262 + xy: 1239, 853 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +power-node-icon-full + rotate: false + xy: 1239, 853 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 power-node-large rotate: false - xy: 1716, 1003 + xy: 1346, 1493 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +power-node-large-icon-full + rotate: false + xy: 1346, 1493 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 power-source rotate: false - xy: 1331, 248 + xy: 1273, 887 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 power-void rotate: false - xy: 1365, 248 + xy: 1341, 955 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +power-void-icon-full + rotate: false + xy: 1341, 955 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 rtg-generator rotate: false - xy: 1650, 937 + xy: 1544, 1465 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +rtg-generator-icon-full + rotate: false + xy: 1544, 1465 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 rtg-generator-top rotate: false - xy: 567, 303 + xy: 1239, 751 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 solar-panel rotate: false - xy: 635, 287 + xy: 1273, 683 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +solar-panel-icon-full + rotate: false + xy: 1273, 683 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 solar-panel-large rotate: false - xy: 1395, 1267 + xy: 881, 262 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +solar-panel-large-icon-full + rotate: false + xy: 881, 262 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 surge-tower rotate: false - xy: 359, 544 + xy: 1045, 1419 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +surge-tower-icon-full + rotate: false + xy: 1045, 1419 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 thermal-generator rotate: false - xy: 293, 280 + xy: 913, 1287 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +thermal-generator-icon-full + rotate: false + xy: 913, 1287 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 thorium-reactor rotate: false - xy: 1591, 1267 + xy: 754, 1634 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +thorium-reactor-icon-full + rotate: false + xy: 754, 1634 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 thorium-reactor-center rotate: false - xy: 1689, 1267 + xy: 754, 1536 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 thorium-reactor-lights rotate: false - xy: 1787, 1267 + xy: 779, 1438 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 turbine-generator rotate: false - xy: 293, 82 + xy: 913, 1089 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +turbine-generator-icon-full + rotate: false + xy: 913, 1089 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +turbine-generator-liquid + rotate: false + xy: 979, 1089 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 turbine-generator-top rotate: false - xy: 359, 148 + xy: 913, 1023 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 alloy-smelter rotate: false - xy: 219, 1541 + xy: 1, 3 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +alloy-smelter-icon-full + rotate: false + xy: 1, 3 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 alloy-smelter-top rotate: false - xy: 1379, 1561 + xy: 1934, 1951 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 blast-mixer rotate: false - xy: 1983, 1519 + xy: 651, 588 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +blast-mixer-icon-full + rotate: false + xy: 651, 588 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 coal-centrifuge rotate: false - xy: 1983, 1387 + xy: 295, 26 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +coal-centrifuge-icon-full + rotate: false + xy: 295, 26 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cryofluidmixer-bottom rotate: false - xy: 1831, 1135 + xy: 847, 1010 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cryofluidmixer-liquid rotate: false - xy: 1963, 1123 + xy: 847, 878 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cryofluidmixer-top rotate: false - xy: 792, 1267 + xy: 847, 812 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cultivator rotate: false - xy: 792, 1201 + xy: 847, 746 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cultivator-middle rotate: false - xy: 858, 1271 + xy: 950, 1551 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cultivator-top rotate: false - xy: 858, 1205 + xy: 1016, 1551 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 graphite-press rotate: false - xy: 1122, 1139 + xy: 1148, 1625 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +graphite-press-icon-full + rotate: false + xy: 1148, 1625 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 incinerator rotate: false - xy: 1369, 452 + xy: 1178, 1159 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +incinerator-icon-full + rotate: false + xy: 1178, 1159 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-source rotate: false - xy: 1437, 878 + xy: 1382, 1125 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-source-icon-full + rotate: false + xy: 1382, 1125 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-void rotate: false - xy: 1437, 708 + xy: 1205, 1057 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-void-icon-full + rotate: false + xy: 1205, 1057 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 kiln rotate: false - xy: 1188, 1139 + xy: 1148, 1559 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +kiln-icon-full + rotate: false + xy: 1148, 1559 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 kiln-top rotate: false - xy: 1254, 1185 + xy: 1280, 1625 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 silicon-smelter-top rotate: false - xy: 1254, 1185 + xy: 1280, 1625 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 liquid-source rotate: false - xy: 1805, 869 + xy: 1307, 1091 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-source-icon-full + rotate: false + xy: 1307, 1091 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 melter rotate: false - xy: 1233, 434 + xy: 1273, 1023 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +melter-icon-full + rotate: false + xy: 1273, 1023 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 multi-press rotate: false - xy: 1199, 1337 + xy: 749, 1242 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +multi-press-icon-full + rotate: false + xy: 749, 1242 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 phase-weaver rotate: false - xy: 1254, 1053 + xy: 1544, 1531 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 phase-weaver-bottom rotate: false - xy: 1320, 1053 + xy: 1610, 1531 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 phase-weaver-weave rotate: false - xy: 1452, 1080 + xy: 1742, 1527 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 plastanium-compressor rotate: false - xy: 1452, 1014 + xy: 1808, 1527 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +plastanium-compressor-icon-full + rotate: false + xy: 1808, 1527 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 plastanium-compressor-top rotate: false - xy: 1518, 1061 + xy: 1874, 1527 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 pulverizer rotate: false - xy: 533, 371 + xy: 1375, 955 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulverizer-rotator rotate: false - xy: 533, 303 + xy: 1205, 751 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pump-liquid + rotate: false + xy: 1239, 785 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pyratite-mixer rotate: false - xy: 1782, 1003 + xy: 1412, 1493 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +pyratite-mixer-icon-full + rotate: false + xy: 1412, 1493 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 separator rotate: false - xy: 359, 940 + xy: 1273, 1427 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +separator-icon-full + rotate: false + xy: 1273, 1427 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 separator-liquid rotate: false - xy: 293, 808 + xy: 1339, 1427 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 silicon-smelter rotate: false - xy: 359, 874 + xy: 1405, 1427 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +silicon-smelter-icon-full + rotate: false + xy: 1405, 1427 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spore-press rotate: false - xy: 293, 676 + xy: 1603, 1399 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spore-press-frame0 rotate: false - xy: 359, 742 + xy: 1669, 1399 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spore-press-frame1 rotate: false - xy: 293, 610 + xy: 1735, 1395 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spore-press-frame2 rotate: false - xy: 359, 676 + xy: 1801, 1395 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spore-press-liquid rotate: false - xy: 359, 610 + xy: 1933, 1395 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spore-press-top rotate: false - xy: 293, 478 + xy: 979, 1419 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 container rotate: false - xy: 1983, 1321 + xy: 950, 1617 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +container-icon-full + rotate: false + xy: 950, 1617 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 core-foundation rotate: false - xy: 786, 1793 + xy: 163, 383 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +core-foundation-icon-full + rotate: false + xy: 163, 383 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 core-nucleus rotate: false - xy: 1, 1032 + xy: 1, 1001 + size: 160, 160 + orig: 160, 160 + offset: 0, 0 + index: -1 +core-nucleus-icon-full + rotate: false + xy: 1, 1001 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 core-shard rotate: false - xy: 1575, 1561 + xy: 293, 288 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +core-shard-icon-full + rotate: false + xy: 293, 288 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 launch-pad rotate: false - xy: 807, 1337 + xy: 707, 1340 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +launch-pad-icon-full + rotate: false + xy: 707, 1340 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 launch-pad-large rotate: false - xy: 745, 1627 + xy: 349, 1264 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +launch-pad-large-icon-full + rotate: false + xy: 349, 1264 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 unloader rotate: false - xy: 771, 81 + xy: 1163, 479 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +unloader-icon-full + rotate: false + xy: 1163, 479 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 vault rotate: false - xy: 1395, 1169 + xy: 852, 1561 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +vault-icon-full + rotate: false + xy: 852, 1561 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 arc-heat rotate: false - xy: 1325, 894 + xy: 877, 1461 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-1 rotate: false - xy: 1233, 706 + xy: 1909, 1361 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 block-2 rotate: false - xy: 1983, 1453 + xy: 717, 490 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 block-3 rotate: false - xy: 1477, 1561 + xy: 423, 516 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 block-4 rotate: false - xy: 526, 1757 + xy: 163, 903 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 hail-heat rotate: false - xy: 425, 1 + xy: 609, 1298 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 lancer-heat rotate: false - xy: 1254, 1119 + xy: 1346, 1625 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 meltdown-heat rotate: false - xy: 1005, 1663 + xy: 293, 1134 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 ripple-heat rotate: false - xy: 1689, 1463 + xy: 783, 458 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 salvo-heat rotate: false - xy: 1980, 991 + xy: 1940, 1461 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 salvo-panel-left rotate: false - xy: 302, 1138 + xy: 789, 98 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 salvo-panel-right rotate: false - xy: 368, 1138 + xy: 855, 98 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 scorch-heat rotate: false - xy: 601, 269 + xy: 1341, 819 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 wave-liquid rotate: false - xy: 425, 610 + xy: 979, 693 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 crawler-factory rotate: false - xy: 1633, 1127 + xy: 847, 1208 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 dagger-factory rotate: false - xy: 1633, 1127 + xy: 847, 1208 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +draug-factory + rotate: false + xy: 847, 1208 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 phantom-factory rotate: false - xy: 1633, 1127 + xy: 847, 1208 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spirit-factory rotate: false - xy: 1633, 1127 + xy: 847, 1208 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 wraith-factory rotate: false - xy: 1633, 1127 + xy: 847, 1208 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 crawler-factory-top rotate: false - xy: 1765, 1135 + xy: 847, 1076 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 dagger-factory-top rotate: false - xy: 858, 1139 + xy: 943, 1485 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +draug-factory-top + rotate: false + xy: 459, 54 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 fortress-factory rotate: false - xy: 302, 1204 + xy: 489, 284 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 fortress-factory-top rotate: false - xy: 400, 1204 + xy: 619, 480 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 ghoul-factory-top rotate: false - xy: 400, 1204 + xy: 619, 480 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 titan-factory-top rotate: false - xy: 400, 1204 + xy: 619, 480 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 ghoul-factory rotate: false - xy: 709, 1333 + xy: 587, 186 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 phantom-factory-top rotate: false - xy: 1122, 1073 + xy: 1940, 1593 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 repair-point-base rotate: false - xy: 533, 201 + xy: 1307, 853 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 revenant-factory rotate: false - xy: 1265, 1659 + xy: 423, 1134 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 revenant-factory-top rotate: false - xy: 1525, 1659 + xy: 423, 1004 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 spirit-factory-top rotate: false - xy: 359, 808 + xy: 1537, 1399 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 titan-factory rotate: false - xy: 1885, 1267 + xy: 805, 1340 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 wraith-factory-top rotate: false - xy: 425, 478 + xy: 1045, 1221 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 copper-wall rotate: false - xy: 1301, 826 + xy: 1129, 523 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +copper-wall-icon-full + rotate: false + xy: 1129, 523 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 copper-wall-large rotate: false - xy: 1983, 1255 + xy: 1098, 1691 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +copper-wall-large-icon-full + rotate: false + xy: 1098, 1691 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 door rotate: false - xy: 1335, 486 + xy: 1899, 1289 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +door-icon-full + rotate: false + xy: 1899, 1289 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 door-large rotate: false - xy: 990, 1205 + xy: 525, 120 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +door-large-icon-full + rotate: false + xy: 525, 120 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 door-large-open rotate: false - xy: 1056, 1271 + xy: 591, 120 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 door-open rotate: false - xy: 1335, 452 + xy: 1933, 1293 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-wall rotate: false - xy: 1399, 323 + xy: 1205, 819 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-wall-icon-full + rotate: false + xy: 1205, 819 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-wall-large rotate: false - xy: 1188, 1073 + xy: 1478, 1531 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +phase-wall-large-icon-full + rotate: false + xy: 1478, 1531 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 scrap-wall-gigantic rotate: false - xy: 1785, 1659 + xy: 423, 874 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +scrap-wall-gigantic-icon-full + rotate: false + xy: 423, 874 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 scrap-wall-huge1 rotate: false - xy: 1787, 1365 + xy: 783, 164 + size: 96, 96 + orig: 96, 96 + offset: 0, 0 + index: -1 +scrap-wall-huge-icon-full + rotate: false + xy: 783, 164 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 scrap-wall-huge2 rotate: false - xy: 1885, 1463 + xy: 881, 458 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 scrap-wall-huge3 rotate: false - xy: 1885, 1365 + xy: 881, 360 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 scrap-wall-large1 rotate: false - xy: 359, 1072 + xy: 789, 32 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 scrap-wall-large2 rotate: false - xy: 293, 940 + xy: 855, 32 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 scrap-wall-large3 rotate: false - xy: 359, 1006 + xy: 921, 32 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 scrap-wall-large4 rotate: false - xy: 293, 874 + xy: 1141, 1427 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 scrap-wall1 rotate: false - xy: 601, 235 + xy: 1273, 717 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap-wall-icon-full + rotate: false + xy: 1273, 717 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scrap-wall2 rotate: false - xy: 567, 167 + xy: 1307, 751 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scrap-wall3 rotate: false - xy: 601, 201 + xy: 1341, 785 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scrap-wall4 rotate: false - xy: 567, 133 + xy: 1375, 819 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scrap-wall5 rotate: false - xy: 567, 133 + xy: 1375, 819 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 surge-wall rotate: false - xy: 669, 295 + xy: 1201, 649 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +surge-wall-icon-full + rotate: false + xy: 1201, 649 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 surge-wall-large rotate: false - xy: 293, 412 + xy: 913, 1419 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +surge-wall-large-icon-full + rotate: false + xy: 913, 1419 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 thorium-wall rotate: false - xy: 703, 227 + xy: 1201, 581 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +thorium-wall-icon-full + rotate: false + xy: 1201, 581 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 thorium-wall-large rotate: false - xy: 359, 346 + xy: 979, 1287 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +thorium-wall-large-icon-full + rotate: false + xy: 979, 1287 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 thruster rotate: false - xy: 1005, 1533 + xy: 293, 484 + size: 128, 128 + orig: 128, 128 + offset: 0, 0 + index: -1 +thruster-icon-full + rotate: false + xy: 293, 484 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 titanium-wall rotate: false - xy: 805, 217 + xy: 1371, 547 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium-wall-icon-full + rotate: false + xy: 1371, 547 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-wall-large rotate: false - xy: 293, 148 + xy: 913, 1155 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +titanium-wall-large-icon-full + rotate: false + xy: 913, 1155 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 bullet rotate: false - xy: 526, 1907 + xy: 1029, 616 size: 52, 52 orig: 52, 52 offset: 0, 0 index: -1 bullet-back rotate: false - xy: 1956, 1791 + xy: 1029, 562 size: 52, 52 orig: 52, 52 offset: 0, 0 index: -1 casing rotate: false - xy: 1897, 851 + xy: 903, 1425 size: 8, 16 orig: 8, 16 offset: 0, 0 index: -1 circle-shadow rotate: false - xy: 1, 1194 + xy: 645, 1846 size: 201, 201 orig: 201, 201 offset: 0, 0 index: -1 error rotate: false - xy: 641, 821 + xy: 1083, 620 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 laser rotate: false - xy: 492, 1154 + xy: 387, 42 size: 4, 48 orig: 4, 48 offset: 0, 0 index: -1 laser-end rotate: false - xy: 1956, 1845 + xy: 759, 1772 size: 72, 72 orig: 72, 72 offset: 0, 0 index: -1 minelaser rotate: false - xy: 2043, 875 + xy: 155, 303 size: 4, 48 orig: 4, 48 offset: 0, 0 index: -1 minelaser-end rotate: false - xy: 1493, 1146 + xy: 950, 1683 size: 72, 72 orig: 72, 72 offset: 0, 0 index: -1 missile rotate: false - xy: 1249, 986 + xy: 759, 1734 size: 36, 36 orig: 36, 36 offset: 0, 0 index: -1 missile-back rotate: false - xy: 1249, 948 + xy: 1795, 1357 size: 36, 36 orig: 36, 36 offset: 0, 0 index: -1 scale_marker rotate: false - xy: 757, 1029 + xy: 459, 186 size: 4, 4 orig: 4, 4 offset: 0, 0 index: -1 scorch1 rotate: false - xy: 839, 57 + xy: 1163, 377 size: 28, 100 orig: 28, 100 offset: 0, 0 index: -1 scorch2 rotate: false - xy: 870, 137 + xy: 1163, 275 size: 28, 100 orig: 28, 100 offset: 0, 0 index: -1 scorch3 rotate: false - xy: 900, 137 + xy: 1163, 173 size: 28, 100 orig: 28, 100 offset: 0, 0 index: -1 scorch4 rotate: false - xy: 869, 35 + xy: 1409, 1023 size: 28, 100 orig: 28, 100 offset: 0, 0 index: -1 scorch5 rotate: false - xy: 899, 35 + xy: 1409, 921 size: 28, 100 orig: 28, 100 offset: 0, 0 index: -1 shell rotate: false - xy: 1325, 986 + xy: 1833, 1357 size: 36, 36 orig: 36, 36 offset: 0, 0 index: -1 shell-back rotate: false - xy: 1249, 910 + xy: 1871, 1357 size: 36, 36 orig: 36, 36 offset: 0, 0 index: -1 shot rotate: false - xy: 601, 65 + xy: 1375, 717 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 transfer rotate: false - xy: 2043, 825 + xy: 155, 253 size: 4, 48 orig: 4, 48 offset: 0, 0 index: -1 transfer-arrow rotate: false - xy: 805, 183 + xy: 1163, 513 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 transfer-end rotate: false - xy: 1579, 1193 + xy: 1024, 1683 size: 72, 72 orig: 72, 72 offset: 0, 0 index: -1 -alloy-smelter-icon-large +white rotate: false - xy: 491, 913 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -alloy-smelter-icon-medium - rotate: false - xy: 823, 1101 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -alloy-smelter-icon-small - rotate: false - xy: 137, 34 - size: 24, 24 - orig: 24, 24 + xy: 645, 1727 + size: 3, 3 + orig: 3, 3 offset: 0, 0 index: -1 arc rotate: false - xy: 2010, 1811 + xy: 609, 1264 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 arc-icon-full rotate: false - xy: 1233, 876 + xy: 1029, 2 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -arc-icon-large - rotate: false - xy: 491, 863 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -arc-icon-small - rotate: false - xy: 137, 8 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -battery-icon-large - rotate: false - xy: 657, 1029 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -battery-icon-small - rotate: false - xy: 485, 1601 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -battery-large-icon-large - rotate: false - xy: 491, 755 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -battery-large-icon-medium - rotate: false - xy: 1233, 808 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -battery-large-icon-small - rotate: false - xy: 844, 1535 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 blast-drill-icon-full rotate: false - xy: 1490, 1919 + xy: 323, 1394 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 -blast-drill-icon-large +char-icon-full rotate: false - xy: 491, 705 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -blast-drill-icon-medium - rotate: false - xy: 1233, 774 + xy: 1579, 1223 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -blast-drill-icon-small +cliffs-icon-full rotate: false - xy: 533, 5 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -blast-mixer-icon-large - rotate: false - xy: 491, 655 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -blast-mixer-icon-medium - rotate: false - xy: 1233, 740 + xy: 1110, 1135 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -blast-mixer-icon-small - rotate: false - xy: 907, 247 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -bridge-conduit-icon-large - rotate: false - xy: 491, 505 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -bridge-conduit-icon-small - rotate: false - xy: 1471, 886 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -bridge-conveyor-icon-large - rotate: false - xy: 87, 10 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -bridge-conveyor-icon-small - rotate: false - xy: 1467, 279 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -char-icon-large - rotate: false - xy: 491, 455 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -char-icon-small - rotate: false - xy: 933, 247 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -cliffs-icon-large - rotate: false - xy: 490, 405 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -cliffs-icon-small - rotate: false - xy: 1471, 860 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -coal-centrifuge-icon-large - rotate: false - xy: 483, 355 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -coal-centrifuge-icon-medium - rotate: false - xy: 1267, 568 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -coal-centrifuge-icon-small - rotate: false - xy: 1467, 253 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -combustion-generator-icon-large - rotate: false - xy: 483, 305 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -combustion-generator-icon-small - rotate: false - xy: 585, 5 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 conduit-icon-full rotate: false - xy: 1465, 980 + xy: 1103, 863 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -conduit-icon-large - rotate: false - xy: 483, 255 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -conduit-icon-small - rotate: false - xy: 959, 247 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -container-icon-large - rotate: false - xy: 483, 205 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -container-icon-medium - rotate: false - xy: 1567, 927 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -container-icon-small - rotate: false - xy: 1471, 834 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -conveyor-icon-large - rotate: false - xy: 483, 155 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -conveyor-icon-small - rotate: false - xy: 1467, 227 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -copper-wall-icon-large - rotate: false - xy: 483, 105 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -copper-wall-icon-small - rotate: false - xy: 985, 247 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -copper-wall-large-icon-large - rotate: false - xy: 483, 55 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -copper-wall-large-icon-medium - rotate: false - xy: 1301, 792 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -copper-wall-large-icon-small - rotate: false - xy: 1471, 808 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -core-foundation-icon-large - rotate: false - xy: 707, 1029 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -core-foundation-icon-medium - rotate: false - xy: 1301, 758 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -core-foundation-icon-small - rotate: false - xy: 1467, 201 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -core-nucleus-icon-large - rotate: false - xy: 757, 1035 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -core-nucleus-icon-medium - rotate: false - xy: 1301, 724 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -core-nucleus-icon-small - rotate: false - xy: 1011, 247 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -core-shard-icon-large - rotate: false - xy: 807, 1035 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -core-shard-icon-medium - rotate: false - xy: 1301, 690 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -core-shard-icon-small - rotate: false - xy: 1471, 782 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 cracks-1-0 rotate: false - xy: 1301, 656 + xy: 1129, 489 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cracks-1-1 rotate: false - xy: 1301, 622 + xy: 1129, 455 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cracks-1-2 rotate: false - xy: 1301, 588 + xy: 1129, 421 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cracks-1-3 rotate: false - xy: 1301, 554 + xy: 1129, 387 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cracks-1-4 rotate: false - xy: 1301, 520 + xy: 1129, 353 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cracks-1-5 rotate: false - xy: 1301, 486 + xy: 1129, 319 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cracks-1-6 rotate: false - xy: 1335, 860 + xy: 1129, 285 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cracks-1-7 rotate: false - xy: 1335, 826 + xy: 1129, 251 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 cracks-2-0 rotate: false - xy: 807, 1561 + xy: 1016, 1617 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cracks-2-1 rotate: false - xy: 1653, 1201 + xy: 1164, 1691 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cracks-2-2 rotate: false - xy: 1719, 1201 + xy: 1230, 1691 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cracks-2-3 rotate: false - xy: 1785, 1201 + xy: 1296, 1691 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cracks-2-4 rotate: false - xy: 1851, 1201 + xy: 1362, 1691 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cracks-2-5 rotate: false - xy: 1917, 1201 + xy: 1428, 1691 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cracks-2-6 rotate: false - xy: 1983, 1189 + xy: 393, 126 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cracks-2-7 rotate: false - xy: 1567, 1127 + xy: 847, 1274 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 cracks-3-0 rotate: false - xy: 1673, 1561 + xy: 656, 1634 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 cracks-3-1 rotate: false - xy: 1771, 1561 + xy: 553, 1166 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 cracks-3-2 rotate: false - xy: 1869, 1561 + xy: 553, 1068 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 cracks-3-3 rotate: false - xy: 317, 1498 + xy: 553, 970 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 cracks-3-4 rotate: false - xy: 415, 1498 + xy: 553, 872 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 cracks-3-5 rotate: false - xy: 513, 1529 + xy: 553, 774 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 cracks-3-6 rotate: false - xy: 611, 1529 + xy: 553, 676 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 cracks-3-7 rotate: false - xy: 709, 1529 + xy: 553, 578 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 cracks-4-0 rotate: false - xy: 916, 1793 + xy: 848, 1757 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 cracks-4-1 rotate: false - xy: 1046, 1793 + xy: 978, 1757 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 cracks-4-2 rotate: false - xy: 1176, 1793 + xy: 1108, 1757 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 cracks-4-3 rotate: false - xy: 1306, 1789 + xy: 1238, 1757 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 cracks-4-4 rotate: false - xy: 1436, 1789 + xy: 1368, 1757 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 cracks-4-5 rotate: false - xy: 1566, 1789 + xy: 1498, 1793 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 cracks-4-6 rotate: false - xy: 1696, 1789 + xy: 1628, 1793 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 cracks-4-7 rotate: false - xy: 1826, 1789 + xy: 1758, 1789 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 cracks-5-0 rotate: false - xy: 1, 870 + xy: 848, 1887 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 cracks-5-1 rotate: false - xy: 1, 708 + xy: 1, 839 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 cracks-5-2 rotate: false - xy: 1, 546 + xy: 1010, 1887 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 cracks-5-3 rotate: false - xy: 1, 384 + xy: 1, 677 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 cracks-5-4 rotate: false - xy: 1, 222 + xy: 1172, 1887 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 cracks-5-5 rotate: false - xy: 1, 60 + xy: 1, 515 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 cracks-5-6 rotate: false - xy: 323, 1596 + xy: 1334, 1887 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 cracks-5-7 rotate: false - xy: 582, 1887 + xy: 1, 353 size: 160, 160 orig: 160, 160 offset: 0, 0 index: -1 -craters-icon-large +craters-icon-full rotate: false - xy: 857, 1023 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -craters-icon-small - rotate: false - xy: 1037, 247 - size: 24, 24 - orig: 24, 24 + xy: 1129, 217 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 crawler-factory-icon-full rotate: false - xy: 1699, 1135 + xy: 847, 1142 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -crawler-factory-icon-large - rotate: false - xy: 1007, 1023 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -crawler-factory-icon-medium - rotate: false - xy: 1335, 792 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -crawler-factory-icon-small - rotate: false - xy: 1471, 756 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 cryofluidmixer-icon-full rotate: false - xy: 1897, 1135 + xy: 847, 944 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -cryofluidmixer-icon-large - rotate: false - xy: 1107, 1023 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -cryofluidmixer-icon-medium - rotate: false - xy: 1335, 758 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -cryofluidmixer-icon-small - rotate: false - xy: 1063, 247 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 cultivator-icon-full rotate: false - xy: 792, 1135 + xy: 847, 680 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -cultivator-icon-large - rotate: false - xy: 1157, 1023 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -cultivator-icon-medium - rotate: false - xy: 1335, 724 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -cultivator-icon-small - rotate: false - xy: 1471, 730 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 cyclone rotate: false - xy: 317, 1400 + xy: 99, 3 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 cyclone-icon-full rotate: false - xy: 415, 1400 + xy: 197, 25 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 -cyclone-icon-large - rotate: false - xy: 483, 5 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -cyclone-icon-medium - rotate: false - xy: 1335, 690 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -cyclone-icon-small - rotate: false - xy: 1089, 247 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 dagger-factory-icon-full rotate: false - xy: 924, 1271 + xy: 877, 1495 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -dagger-factory-icon-large +dark-metal-icon-full rotate: false - xy: 541, 813 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -dagger-factory-icon-medium - rotate: false - xy: 1335, 656 + xy: 1129, 183 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -dagger-factory-icon-small +dark-panel-1-icon-full rotate: false - xy: 1471, 704 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -dark-metal-icon-large - rotate: false - xy: 541, 713 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -dark-metal-icon-small - rotate: false - xy: 1115, 247 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -dark-panel-1-icon-large - rotate: false - xy: 541, 663 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -dark-panel-1-icon-small - rotate: false - xy: 1471, 678 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -dark-panel-2-icon-large - rotate: false - xy: 541, 613 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -dark-panel-2-icon-small - rotate: false - xy: 1141, 247 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -dark-panel-3-icon-large - rotate: false - xy: 541, 563 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -dark-panel-3-icon-small - rotate: false - xy: 1471, 652 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -dark-panel-4-icon-large - rotate: false - xy: 541, 513 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -dark-panel-4-icon-small - rotate: false - xy: 1471, 626 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -dark-panel-5-icon-large - rotate: false - xy: 541, 463 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -dark-panel-5-icon-small - rotate: false - xy: 1471, 600 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -dark-panel-6-icon-large - rotate: false - xy: 599, 971 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -dark-panel-6-icon-small - rotate: false - xy: 1471, 574 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -darksand-icon-large - rotate: false - xy: 591, 921 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -darksand-icon-small - rotate: false - xy: 1471, 548 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -darksand-tainted-water-icon-large - rotate: false - xy: 591, 871 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -darksand-tainted-water-icon-small - rotate: false - xy: 1471, 522 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -darksand-water-icon-large - rotate: false - xy: 591, 821 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -darksand-water-icon-small - rotate: false - xy: 1471, 496 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -dart-mech-pad-icon-large - rotate: false - xy: 591, 771 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -dart-mech-pad-icon-medium - rotate: false - xy: 1335, 622 + xy: 1899, 1323 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -dart-mech-pad-icon-small +dark-panel-2-icon-full rotate: false - xy: 1471, 470 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -deepwater-icon-large - rotate: false - xy: 591, 671 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -deepwater-icon-small - rotate: false - xy: 1471, 444 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -delta-mech-pad-icon-large - rotate: false - xy: 591, 471 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -delta-mech-pad-icon-medium - rotate: false - xy: 1335, 588 + xy: 1933, 1327 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -delta-mech-pad-icon-small +dark-panel-3-icon-full rotate: false - xy: 1471, 418 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -differential-generator-icon-large - rotate: false - xy: 649, 979 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -differential-generator-icon-medium - rotate: false - xy: 1335, 554 + xy: 1967, 1327 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -differential-generator-icon-small +dark-panel-4-icon-full rotate: false - xy: 1471, 392 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -distributor-icon-large - rotate: false - xy: 699, 979 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -distributor-icon-medium - rotate: false - xy: 1335, 520 + xy: 2001, 1327 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -distributor-icon-small +dark-panel-5-icon-full rotate: false - xy: 1497, 867 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -door-icon-large - rotate: false - xy: 541, 413 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -door-icon-small - rotate: false - xy: 1523, 867 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -door-large-icon-large - rotate: false - xy: 591, 421 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -door-large-icon-medium - rotate: false - xy: 1301, 452 + xy: 1695, 1281 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -door-large-icon-small +dark-panel-6-icon-full rotate: false - xy: 1497, 841 - size: 24, 24 - orig: 24, 24 + xy: 1729, 1285 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 -dunerocks-icon-large +darksand-icon-full rotate: false - xy: 641, 921 - size: 48, 48 - orig: 48, 48 + xy: 1763, 1285 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 -dunerocks-icon-small +darksand-tainted-water-icon-full rotate: false - xy: 1549, 867 - size: 24, 24 - orig: 24, 24 + xy: 1797, 1289 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +darksand-water-icon-full + rotate: false + xy: 1831, 1289 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +deepwater-icon-full + rotate: false + xy: 1865, 1289 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +draug-factory-icon-full + rotate: false + xy: 657, 120 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 +dunerocks-icon-full + rotate: false + xy: 1967, 1293 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 duo rotate: false - xy: 1359, 894 + xy: 2001, 1293 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 duo-icon-full rotate: false - xy: 1393, 901 + xy: 1545, 1181 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -duo-icon-large - rotate: false - xy: 641, 871 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -duo-icon-small - rotate: false - xy: 1497, 815 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -force-projector-icon-large - rotate: false - xy: 641, 605 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -force-projector-icon-medium - rotate: false - xy: 1369, 826 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -force-projector-icon-small - rotate: false - xy: 1523, 841 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 fortress-factory-icon-full rotate: false - xy: 400, 1302 + xy: 489, 186 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 -fortress-factory-icon-large - rotate: false - xy: 641, 555 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -fortress-factory-icon-medium - rotate: false - xy: 1369, 792 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -fortress-factory-icon-small - rotate: false - xy: 1575, 867 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 fuse rotate: false - xy: 513, 1333 + xy: 587, 382 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 fuse-icon-full rotate: false - xy: 611, 1333 + xy: 587, 284 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 -fuse-icon-large - rotate: false - xy: 641, 505 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -fuse-icon-medium - rotate: false - xy: 1369, 758 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -fuse-icon-small - rotate: false - xy: 1497, 789 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 ghoul-factory-icon-full rotate: false - xy: 498, 1235 + xy: 685, 382 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 -ghoul-factory-icon-large +grass-icon-full rotate: false - xy: 641, 455 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ghoul-factory-icon-medium - rotate: false - xy: 1369, 724 + xy: 1579, 1189 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ghoul-factory-icon-small - rotate: false - xy: 1523, 815 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -glaive-ship-pad-icon-large - rotate: false - xy: 691, 929 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -glaive-ship-pad-icon-medium - rotate: false - xy: 1369, 690 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -glaive-ship-pad-icon-small - rotate: false - xy: 1549, 841 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -graphite-press-icon-large - rotate: false - xy: 691, 879 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -graphite-press-icon-medium - rotate: false - xy: 1369, 656 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -graphite-press-icon-small - rotate: false - xy: 1601, 867 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -grass-icon-large - rotate: false - xy: 691, 829 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -grass-icon-small - rotate: false - xy: 1497, 763 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 hail rotate: false - xy: 1369, 622 + xy: 1161, 1193 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 hail-icon-full rotate: false - xy: 1369, 588 + xy: 1195, 1193 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -hail-icon-large +holostone-icon-full rotate: false - xy: 691, 779 - size: 48, 48 - orig: 48, 48 + xy: 1229, 1193 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 -hail-icon-small +hotrock-icon-full rotate: false - xy: 1523, 789 - size: 24, 24 - orig: 24, 24 + xy: 1263, 1193 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 -holostone-icon-large +ice-icon-full rotate: false - xy: 691, 679 - size: 48, 48 - orig: 48, 48 + xy: 1297, 1193 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 -holostone-icon-small +ice-snow-icon-full rotate: false - xy: 1549, 815 - size: 24, 24 - orig: 24, 24 + xy: 1331, 1193 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 -hotrock-icon-large +icerocks-icon-full rotate: false - xy: 691, 629 - size: 48, 48 - orig: 48, 48 + xy: 1365, 1193 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 -hotrock-icon-small +ignarock-icon-full rotate: false - xy: 1575, 841 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ice-icon-large - rotate: false - xy: 691, 579 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ice-icon-small - rotate: false - xy: 1497, 737 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ice-snow-icon-large - rotate: false - xy: 691, 529 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ice-snow-icon-small - rotate: false - xy: 1523, 763 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -icerocks-icon-large - rotate: false - xy: 691, 479 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -icerocks-icon-small - rotate: false - xy: 1549, 789 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ignarock-icon-large - rotate: false - xy: 691, 429 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ignarock-icon-small - rotate: false - xy: 1523, 737 - size: 24, 24 - orig: 24, 24 + xy: 1399, 1193 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 impact-reactor-icon-full rotate: false - xy: 163, 804 + xy: 1628, 1663 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 -impact-reactor-icon-large - rotate: false - xy: 591, 371 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -impact-reactor-icon-medium - rotate: false - xy: 1369, 486 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -impact-reactor-icon-small - rotate: false - xy: 1549, 763 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -incinerator-icon-large - rotate: false - xy: 641, 355 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -incinerator-icon-small - rotate: false - xy: 1575, 789 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 item-blast-compound-medium rotate: false - xy: 1497, 685 + xy: 583, 1412 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-blast-compound-small rotate: false - xy: 163, 6 + xy: 583, 1394 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-blast-compound-xlarge rotate: false - xy: 1254, 1295 + xy: 987, 127 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 +item-blast-compound-xxlarge + rotate: false + xy: 1079, 354 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 item-coal-medium rotate: false - xy: 1523, 711 + xy: 847, 654 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-coal-small rotate: false - xy: 181, 6 + xy: 1160, 1175 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-coal-xlarge rotate: false - xy: 1650, 1085 + xy: 1561, 1257 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 +item-coal-xxlarge + rotate: false + xy: 1079, 304 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 item-copper-medium rotate: false - xy: 1549, 737 + xy: 873, 654 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-copper-small rotate: false - xy: 199, 6 + xy: 155, 105 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-copper-xlarge rotate: false - xy: 1191, 881 + xy: 1611, 1307 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 +item-copper-xxlarge + rotate: false + xy: 1079, 254 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 item-graphite-medium rotate: false - xy: 1575, 763 + xy: 1934, 1925 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-graphite-small rotate: false - xy: 217, 6 + xy: 852, 1543 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-graphite-xlarge rotate: false - xy: 1207, 1031 + xy: 987, 85 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 +item-graphite-xxlarge + rotate: false + xy: 1079, 204 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 item-lead-medium rotate: false - xy: 1601, 773 + xy: 521, 588 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-lead-small rotate: false - xy: 235, 6 + xy: 723, 168 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-lead-xlarge rotate: false - xy: 263, 1401 + xy: 1029, 120 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 +item-lead-xxlarge + rotate: false + xy: 1079, 154 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 item-metaglass-medium rotate: false - xy: 1497, 659 + xy: 423, 490 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-metaglass-small rotate: false - xy: 253, 6 + xy: 913, 559 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-metaglass-xlarge rotate: false - xy: 1254, 1253 + xy: 1653, 1307 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 +item-metaglass-xxlarge + rotate: false + xy: 1101, 1369 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 item-phase-fabric-medium rotate: false - xy: 1523, 685 + xy: 219, 1164 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-phase-fabric-small rotate: false - xy: 271, 6 + xy: 1451, 1409 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-phase-fabric-xlarge rotate: false - xy: 1191, 839 + xy: 987, 43 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 +item-phase-fabric-xxlarge + rotate: false + xy: 1151, 1377 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 item-plastanium-medium rotate: false - xy: 1549, 711 + xy: 361, 66 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-plastanium-small rotate: false - xy: 2028, 1793 + xy: 197, 7 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-plastanium-xlarge rotate: false - xy: 1191, 797 + xy: 987, 1 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 +item-plastanium-xxlarge + rotate: false + xy: 1201, 1377 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 item-pyratite-medium rotate: false - xy: 1575, 737 + xy: 1111, 1459 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-pyratite-small rotate: false - xy: 1705, 685 + xy: 877, 1443 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-pyratite-xlarge rotate: false - xy: 1191, 755 + xy: 1029, 78 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 +item-pyratite-xxlarge + rotate: false + xy: 1251, 1377 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 item-sand-medium rotate: false - xy: 1601, 747 + xy: 2006, 1463 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-sand-small rotate: false - xy: 1845, 825 + xy: 895, 1443 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-sand-xlarge rotate: false - xy: 1191, 713 + xy: 1029, 36 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 +item-sand-xxlarge + rotate: false + xy: 1301, 1377 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 item-scrap-medium rotate: false - xy: 1497, 633 + xy: 1197, 487 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-scrap-small rotate: false - xy: 1653, 640 + xy: 1103, 675 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-scrap-xlarge rotate: false - xy: 1191, 671 + xy: 1071, 112 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 +item-scrap-xxlarge + rotate: false + xy: 1351, 1377 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 item-silicon-medium rotate: false - xy: 1523, 659 + xy: 1231, 521 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-silicon-small rotate: false - xy: 1679, 669 + xy: 1977, 1377 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-silicon-xlarge rotate: false - xy: 1191, 629 + xy: 1071, 70 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 -item-source-icon-large +item-silicon-xxlarge rotate: false - xy: 691, 379 + xy: 1401, 1377 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -item-source-icon-small - rotate: false - xy: 1549, 685 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 item-spore-pod-medium rotate: false - xy: 1575, 711 + xy: 1129, 157 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-spore-pod-small rotate: false - xy: 567, 395 + xy: 1986, 1933 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-spore-pod-xlarge rotate: false - xy: 1191, 587 + xy: 1071, 28 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 +item-spore-pod-xxlarge + rotate: false + xy: 1111, 1319 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 item-surge-alloy-medium rotate: false - xy: 1601, 721 + xy: 1433, 1201 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-surge-alloy-small rotate: false - xy: 567, 377 + xy: 475, 498 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-surge-alloy-xlarge rotate: false - xy: 1191, 545 + xy: 1461, 1207 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 +item-surge-alloy-xxlarge + rotate: false + xy: 1111, 1269 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 item-thorium-medium rotate: false - xy: 1497, 607 + xy: 1409, 895 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-thorium-small rotate: false - xy: 839, 39 + xy: 271, 1172 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-thorium-xlarge rotate: false - xy: 1191, 503 + xy: 1503, 1207 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 +item-thorium-xxlarge + rotate: false + xy: 1111, 1219 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 item-titanium-medium rotate: false - xy: 1523, 633 + xy: 1960, 1925 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 item-titanium-small rotate: false - xy: 1601, 391 + xy: 1283, 529 size: 16, 16 orig: 16, 16 offset: 0, 0 index: -1 item-titanium-xlarge rotate: false - xy: 1191, 461 + xy: 1711, 1353 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 -item-void-icon-large +item-titanium-xxlarge rotate: false - xy: 691, 329 + xy: 1110, 1169 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -item-void-icon-small - rotate: false - xy: 1549, 659 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -javelin-ship-pad-icon-large - rotate: false - xy: 741, 929 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -javelin-ship-pad-icon-medium - rotate: false - xy: 1437, 674 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -javelin-ship-pad-icon-small - rotate: false - xy: 1575, 685 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -junction-icon-large - rotate: false - xy: 741, 829 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -junction-icon-small - rotate: false - xy: 1601, 695 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -kiln-icon-large - rotate: false - xy: 741, 779 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -kiln-icon-medium - rotate: false - xy: 1437, 606 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -kiln-icon-small - rotate: false - xy: 1497, 581 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 lancer rotate: false - xy: 1320, 1185 + xy: 1214, 1559 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 lancer-icon-full rotate: false - xy: 1320, 1119 + xy: 1280, 1559 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -lancer-icon-large - rotate: false - xy: 741, 729 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -lancer-icon-medium - rotate: false - xy: 1437, 572 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -lancer-icon-small - rotate: false - xy: 1523, 607 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 laser-drill-icon-full rotate: false - xy: 498, 1137 + xy: 295, 92 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 -laser-drill-icon-large - rotate: false - xy: 741, 679 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -laser-drill-icon-medium - rotate: false - xy: 1437, 538 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -laser-drill-icon-small - rotate: false - xy: 1549, 633 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -launch-pad-icon-large - rotate: false - xy: 741, 629 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -launch-pad-icon-medium - rotate: false - xy: 1437, 504 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -launch-pad-icon-small - rotate: false - xy: 1575, 659 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -launch-pad-large-icon-large - rotate: false - xy: 741, 579 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -launch-pad-large-icon-medium - rotate: false - xy: 1437, 470 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -launch-pad-large-icon-small - rotate: false - xy: 1601, 669 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -liquid-junction-icon-large - rotate: false - xy: 741, 479 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -liquid-junction-icon-small - rotate: false - xy: 1497, 555 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 liquid-router-icon-full rotate: false - xy: 1669, 869 + xy: 1171, 955 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -liquid-router-icon-large - rotate: false - xy: 741, 429 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -liquid-router-icon-small - rotate: false - xy: 1523, 581 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -liquid-source-icon-large - rotate: false - xy: 741, 379 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -liquid-source-icon-small - rotate: false - xy: 1549, 607 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 liquid-tank-icon-full rotate: false - xy: 905, 1337 + xy: 651, 1144 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 -liquid-tank-icon-large +magmarock-icon-full rotate: false - xy: 741, 329 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -liquid-tank-icon-medium - rotate: false - xy: 1839, 869 + xy: 1205, 955 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -liquid-tank-icon-small - rotate: false - xy: 1575, 633 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -magmarock-icon-large - rotate: false - xy: 799, 985 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -magmarock-icon-small - rotate: false - xy: 1601, 643 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 mass-driver rotate: false - xy: 1101, 1435 + xy: 651, 850 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 mass-driver-icon-full rotate: false - xy: 1199, 1435 + xy: 651, 654 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 -mass-driver-icon-large - rotate: false - xy: 849, 973 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -mass-driver-icon-medium - rotate: false - xy: 1907, 857 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -mass-driver-icon-small - rotate: false - xy: 1497, 529 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 mech-icon-alpha-mech rotate: false - xy: 899, 973 + xy: 1161, 1227 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 mech-icon-dart-ship rotate: false - xy: 949, 973 + xy: 1211, 1277 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 mech-icon-delta-mech rotate: false - xy: 999, 973 + xy: 1261, 1327 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 mech-icon-glaive-ship rotate: false - xy: 425, 217 + xy: 1045, 960 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 mech-icon-javelin-ship rotate: false - xy: 1049, 973 + xy: 1211, 1227 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 mech-icon-omega-mech rotate: false - xy: 425, 159 + xy: 584, 1539 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 mech-icon-tau-mech rotate: false - xy: 425, 101 + xy: 1045, 902 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 mech-icon-trident-ship rotate: false - xy: 425, 43 + xy: 1045, 844 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 mechanical-drill-icon-full rotate: false - xy: 1699, 1069 + xy: 1346, 1559 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -mechanical-drill-icon-large - rotate: false - xy: 1099, 973 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -mechanical-drill-icon-medium - rotate: false - xy: 1941, 857 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -mechanical-drill-icon-small - rotate: false - xy: 1523, 555 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -mechanical-pump-icon-large - rotate: false - xy: 1149, 973 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -mechanical-pump-icon-small - rotate: false - xy: 1549, 581 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 meltdown rotate: false - xy: 875, 1663 + xy: 479, 1264 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 meltdown-icon-full rotate: false - xy: 1135, 1663 + xy: 293, 1004 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 -meltdown-icon-large +metal-floor-2-icon-full rotate: false - xy: 799, 935 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -meltdown-icon-medium - rotate: false - xy: 2009, 857 + xy: 1171, 887 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -meltdown-icon-small +metal-floor-3-icon-full rotate: false - xy: 1575, 607 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -melter-icon-large - rotate: false - xy: 791, 885 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -melter-icon-small - rotate: false - xy: 1601, 617 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -mend-projector-icon-large - rotate: false - xy: 791, 835 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -mend-projector-icon-medium - rotate: false - xy: 1267, 432 + xy: 1205, 921 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -mend-projector-icon-small +metal-floor-5-icon-full rotate: false - xy: 1497, 503 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -mender-icon-large - rotate: false - xy: 791, 785 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -mender-icon-small - rotate: false - xy: 1523, 529 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -metal-floor-2-icon-large - rotate: false - xy: 791, 735 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -metal-floor-2-icon-small - rotate: false - xy: 1549, 555 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -metal-floor-3-icon-large - rotate: false - xy: 791, 685 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -metal-floor-3-icon-small - rotate: false - xy: 1575, 581 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -metal-floor-5-icon-large - rotate: false - xy: 791, 635 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -metal-floor-5-icon-small - rotate: false - xy: 1601, 591 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -metal-floor-damaged-icon-large - rotate: false - xy: 791, 585 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -metal-floor-damaged-icon-small - rotate: false - xy: 1497, 477 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -metal-floor-icon-large - rotate: false - xy: 791, 535 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -metal-floor-icon-small - rotate: false - xy: 1523, 503 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -moss-icon-large - rotate: false - xy: 791, 485 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -moss-icon-small - rotate: false - xy: 1549, 529 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -multi-press-icon-large - rotate: false - xy: 791, 435 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -multi-press-icon-medium - rotate: false - xy: 1229, 332 + xy: 1239, 955 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -multi-press-icon-small +metal-floor-damaged-icon-full rotate: false - xy: 1575, 555 - size: 24, 24 - orig: 24, 24 + xy: 1273, 989 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-icon-full + rotate: false + xy: 1307, 1023 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +moss-icon-full + rotate: false + xy: 1341, 1057 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 oil-extractor-icon-full rotate: false - xy: 1297, 1349 + xy: 749, 1046 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 -oil-extractor-icon-large - rotate: false - xy: 791, 385 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -oil-extractor-icon-medium - rotate: false - xy: 1229, 298 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -oil-extractor-icon-small - rotate: false - xy: 1601, 565 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -omega-mech-pad-icon-large - rotate: false - xy: 791, 335 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -omega-mech-pad-icon-medium - rotate: false - xy: 1263, 398 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -omega-mech-pad-icon-small - rotate: false - xy: 1497, 451 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 ore-coal-icon-full rotate: false - xy: 1263, 364 + xy: 1375, 1091 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-coal-icon-medium rotate: false - xy: 1263, 364 + xy: 1375, 1091 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-coal-icon-large rotate: false - xy: 849, 923 + xy: 1261, 1277 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 ore-coal-icon-small rotate: false - xy: 1523, 477 + xy: 449, 490 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 ore-copper-icon-full rotate: false - xy: 1263, 330 + xy: 1171, 853 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-copper-icon-medium rotate: false - xy: 1263, 330 + xy: 1171, 853 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-copper-icon-large rotate: false - xy: 899, 923 + xy: 1311, 1327 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 ore-copper-icon-small rotate: false - xy: 1549, 503 + xy: 245, 1164 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 ore-lead-icon-full rotate: false - xy: 1263, 296 + xy: 1205, 887 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-lead-icon-medium rotate: false - xy: 1263, 296 + xy: 1205, 887 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-lead-icon-large rotate: false - xy: 949, 923 + xy: 1261, 1227 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 ore-lead-icon-small rotate: false - xy: 1575, 529 + xy: 361, 40 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 ore-scrap-icon-full rotate: false - xy: 1301, 418 + xy: 1239, 921 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-scrap-icon-medium rotate: false - xy: 1301, 418 + xy: 1239, 921 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-scrap-icon-large rotate: false - xy: 999, 923 + xy: 1311, 1277 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 ore-scrap-icon-small rotate: false - xy: 1601, 539 + xy: 1111, 1433 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 ore-thorium-icon-full rotate: false - xy: 1335, 418 + xy: 1273, 955 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-thorium-icon-medium rotate: false - xy: 1335, 418 + xy: 1273, 955 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-thorium-icon-large rotate: false - xy: 1049, 923 + xy: 1361, 1327 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 ore-thorium-icon-small rotate: false - xy: 1497, 425 + xy: 1257, 521 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 ore-titanium-icon-full rotate: false - xy: 1369, 418 + xy: 1307, 989 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-titanium-icon-medium rotate: false - xy: 1369, 418 + xy: 1307, 989 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-titanium-icon-large rotate: false - xy: 1099, 923 + xy: 1311, 1227 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 ore-titanium-icon-small rotate: false - xy: 1523, 451 + xy: 1409, 869 size: 24, 24 orig: 24, 24 offset: 0, 0 index: -1 -overdrive-projector-icon-large +pebbles-icon-full rotate: false - xy: 1149, 923 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -overdrive-projector-icon-medium - rotate: false - xy: 1297, 384 + xy: 1375, 1057 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -overdrive-projector-icon-small - rotate: false - xy: 1549, 477 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -overflow-gate-icon-large - rotate: false - xy: 841, 873 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -overflow-gate-icon-small - rotate: false - xy: 1575, 503 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -pebbles-icon-large - rotate: false - xy: 841, 823 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -pebbles-icon-small - rotate: false - xy: 1601, 513 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 phantom-factory-icon-full rotate: false - xy: 1056, 1073 + xy: 1874, 1593 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -phantom-factory-icon-large - rotate: false - xy: 891, 873 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -phantom-factory-icon-medium - rotate: false - xy: 1331, 384 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -phantom-factory-icon-small - rotate: false - xy: 1497, 399 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -phase-conduit-icon-large - rotate: false - xy: 841, 773 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -phase-conduit-icon-small - rotate: false - xy: 1523, 425 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -phase-conveyor-icon-large - rotate: false - xy: 891, 823 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -phase-conveyor-icon-small - rotate: false - xy: 1549, 451 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -phase-wall-icon-large - rotate: false - xy: 941, 873 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -phase-wall-icon-small - rotate: false - xy: 1575, 477 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -phase-wall-large-icon-large - rotate: false - xy: 841, 723 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -phase-wall-large-icon-medium - rotate: false - xy: 1297, 282 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -phase-wall-large-icon-small - rotate: false - xy: 1601, 487 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 phase-weaver-icon-full rotate: false - xy: 1386, 1037 + xy: 1676, 1531 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -phase-weaver-icon-large +pine-icon-full rotate: false - xy: 891, 773 + xy: 1361, 1277 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -phase-weaver-icon-medium - rotate: false - xy: 1331, 282 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -phase-weaver-icon-small - rotate: false - xy: 1523, 399 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -pine-icon-medium - rotate: false - xy: 1365, 282 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -pine-icon-small - rotate: false - xy: 1549, 425 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -plastanium-compressor-icon-large - rotate: false - xy: 941, 823 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -plastanium-compressor-icon-medium - rotate: false - xy: 1399, 289 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -plastanium-compressor-icon-small - rotate: false - xy: 1575, 451 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 pneumatic-drill-icon-full rotate: false - xy: 1518, 995 + xy: 1148, 1493 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -pneumatic-drill-icon-large +power-source-icon-full rotate: false - xy: 991, 873 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -pneumatic-drill-icon-medium - rotate: false - xy: 1229, 264 + xy: 1307, 921 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -pneumatic-drill-icon-small - rotate: false - xy: 1601, 461 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -power-node-icon-large - rotate: false - xy: 841, 673 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -power-node-icon-small - rotate: false - xy: 1549, 399 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -power-node-large-icon-large - rotate: false - xy: 891, 723 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -power-node-large-icon-medium - rotate: false - xy: 1297, 248 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -power-node-large-icon-small - rotate: false - xy: 1575, 425 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -power-source-icon-large - rotate: false - xy: 941, 773 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -power-source-icon-small - rotate: false - xy: 1601, 435 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -power-void-icon-large - rotate: false - xy: 991, 823 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -power-void-icon-small - rotate: false - xy: 1575, 399 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 pulse-conduit-icon-full rotate: false - xy: 1399, 255 + xy: 1375, 989 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -pulse-conduit-icon-large - rotate: false - xy: 1041, 873 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -pulse-conduit-icon-small - rotate: false - xy: 1601, 409 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 pulverizer-icon-full rotate: false - xy: 533, 337 + xy: 1171, 717 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -pulverizer-icon-large - rotate: false - xy: 841, 623 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -pulverizer-icon-small - rotate: false - xy: 930, 221 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -pyratite-mixer-icon-large - rotate: false - xy: 891, 673 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -pyratite-mixer-icon-medium - rotate: false - xy: 533, 269 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -pyratite-mixer-icon-small - rotate: false - xy: 930, 195 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 repair-point rotate: false - xy: 533, 235 + xy: 1273, 819 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 repair-point-icon-full rotate: false - xy: 533, 167 + xy: 1341, 887 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -repair-point-icon-large - rotate: false - xy: 991, 773 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -repair-point-icon-small - rotate: false - xy: 956, 221 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 revenant-factory-icon-full rotate: false - xy: 1395, 1659 + xy: 293, 874 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 -revenant-factory-icon-large - rotate: false - xy: 1041, 823 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -revenant-factory-icon-medium - rotate: false - xy: 533, 133 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -revenant-factory-icon-small - rotate: false - xy: 956, 195 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 ripple rotate: false - xy: 1591, 1365 + xy: 815, 556 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 ripple-icon-full rotate: false - xy: 1689, 1365 + xy: 783, 360 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 -ripple-icon-large +rock-icon-full rotate: false - xy: 841, 573 + xy: 1411, 1277 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -ripple-icon-medium +rocks-icon-full rotate: false - xy: 533, 99 + xy: 1375, 921 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -ripple-icon-small +salt-icon-full rotate: false - xy: 930, 169 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -rock-icon-medium - rotate: false - xy: 533, 65 + xy: 1273, 785 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -rock-icon-small +saltrocks-icon-full rotate: false - xy: 982, 221 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -rocks-icon-large - rotate: false - xy: 891, 623 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -rocks-icon-small - rotate: false - xy: 982, 195 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -rotary-pump-icon-large - rotate: false - xy: 941, 673 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -rotary-pump-icon-medium - rotate: false - xy: 533, 31 + xy: 1307, 819 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -rotary-pump-icon-small - rotate: false - xy: 930, 143 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -router-icon-large - rotate: false - xy: 991, 723 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -router-icon-small - rotate: false - xy: 956, 169 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -rtg-generator-icon-large - rotate: false - xy: 1041, 773 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -rtg-generator-icon-medium - rotate: false - xy: 601, 337 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -rtg-generator-icon-small - rotate: false - xy: 1008, 221 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -salt-icon-large - rotate: false - xy: 1091, 823 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -salt-icon-small - rotate: false - xy: 1008, 195 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -saltrocks-icon-large - rotate: false - xy: 1141, 873 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -saltrocks-icon-small - rotate: false - xy: 956, 143 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 salvo rotate: false - xy: 1914, 925 + xy: 1874, 1461 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 salvo-icon-full rotate: false - xy: 1980, 925 + xy: 723, 98 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -salvo-icon-large +sand-boulder-icon-full rotate: false - xy: 841, 523 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -salvo-icon-medium - rotate: false - xy: 567, 269 + xy: 1341, 853 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -salvo-icon-small +sand-icon-full rotate: false - xy: 982, 169 - size: 24, 24 - orig: 24, 24 + xy: 1375, 887 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 -sand-icon-large +sand-water-icon-full rotate: false - xy: 891, 573 - size: 48, 48 - orig: 48, 48 + xy: 1239, 717 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 -sand-icon-small +sandrocks-icon-full rotate: false - xy: 1034, 221 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -sand-water-icon-large - rotate: false - xy: 941, 623 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -sand-water-icon-small - rotate: false - xy: 1034, 195 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -sandrocks-icon-large - rotate: false - xy: 991, 673 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -sandrocks-icon-small - rotate: false - xy: 982, 143 - size: 24, 24 - orig: 24, 24 + xy: 1273, 751 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 scatter rotate: false - xy: 293, 1072 + xy: 921, 98 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 scatter-icon-full rotate: false - xy: 293, 1006 + xy: 723, 32 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -scatter-icon-large - rotate: false - xy: 1041, 723 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -scatter-icon-medium - rotate: false - xy: 601, 303 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -scatter-icon-small - rotate: false - xy: 1008, 169 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 scorch rotate: false - xy: 567, 235 + xy: 1307, 785 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scorch-icon-full rotate: false - xy: 567, 201 + xy: 1375, 853 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -scorch-icon-large +scrap-wall-large-icon-full rotate: false - xy: 1091, 773 - size: 48, 48 - orig: 48, 48 + xy: 1207, 1427 + size: 64, 64 + orig: 64, 64 offset: 0, 0 index: -1 -scorch-icon-small +shale-boulder-icon-full rotate: false - xy: 1060, 221 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -scrap-wall-gigantic-icon-large - rotate: false - xy: 1141, 823 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -scrap-wall-gigantic-icon-medium - rotate: false - xy: 601, 167 + xy: 1307, 717 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -scrap-wall-gigantic-icon-small +shale-icon-full rotate: false - xy: 1060, 195 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -scrap-wall-huge-icon-large - rotate: false - xy: 841, 473 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -scrap-wall-huge-icon-medium - rotate: false - xy: 567, 99 + xy: 1341, 751 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -scrap-wall-huge-icon-small +shalerocks-icon-full rotate: false - xy: 1008, 143 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -scrap-wall-icon-large - rotate: false - xy: 891, 523 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -scrap-wall-icon-small - rotate: false - xy: 1034, 169 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -scrap-wall-large-icon-large - rotate: false - xy: 941, 573 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -scrap-wall-large-icon-medium - rotate: false - xy: 601, 133 + xy: 1375, 785 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -scrap-wall-large-icon-small +shock-mine-icon-full rotate: false - xy: 1086, 221 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -separator-icon-large - rotate: false - xy: 991, 623 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -separator-icon-medium - rotate: false - xy: 601, 99 + xy: 1375, 751 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -separator-icon-small +shrubs-icon-full rotate: false - xy: 1086, 195 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -shale-boulder-icon-large - rotate: false - xy: 1041, 673 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -shale-boulder-icon-small - rotate: false - xy: 1034, 143 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -shale-icon-large - rotate: false - xy: 1091, 723 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -shale-icon-small - rotate: false - xy: 1060, 169 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -shalerocks-icon-large - rotate: false - xy: 1141, 773 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -shalerocks-icon-small - rotate: false - xy: 1112, 221 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -shock-mine-icon-large - rotate: false - xy: 841, 423 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -shock-mine-icon-small - rotate: false - xy: 1627, 801 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -shrubs-icon-large - rotate: false - xy: 941, 523 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -shrubs-icon-small - rotate: false - xy: 1679, 843 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -silicon-smelter-icon-large - rotate: false - xy: 991, 573 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -silicon-smelter-icon-medium - rotate: false - xy: 601, 31 + xy: 1171, 683 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -silicon-smelter-icon-small +snow-icon-full rotate: false - xy: 1653, 806 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -snow-icon-large - rotate: false - xy: 1041, 623 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -snow-icon-small - rotate: false - xy: 1112, 195 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -snowrock-icon-medium - rotate: false - xy: 635, 321 + xy: 1205, 683 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -snowrock-icon-small +snow-pine-icon-full rotate: false - xy: 1060, 143 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -snowrocks-icon-large - rotate: false - xy: 1091, 673 + xy: 1461, 1349 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -snowrocks-icon-small +snowrock-icon-full rotate: false - xy: 1086, 169 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -solar-panel-icon-large - rotate: false - xy: 1141, 723 + xy: 1511, 1349 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -solar-panel-icon-small +snowrocks-icon-full rotate: false - xy: 1138, 221 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -solar-panel-large-icon-large - rotate: false - xy: 841, 373 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -solar-panel-large-icon-medium - rotate: false - xy: 635, 253 + xy: 1239, 683 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -solar-panel-large-icon-small +spawn-icon-full rotate: false - xy: 1627, 775 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -sorter-icon-large - rotate: false - xy: 891, 423 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -sorter-icon-small - rotate: false - xy: 1705, 843 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -spawn-icon-large - rotate: false - xy: 941, 473 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -spawn-icon-small - rotate: false - xy: 1679, 817 - size: 24, 24 - orig: 24, 24 + xy: 1341, 683 + size: 32, 32 + orig: 32, 32 offset: 0, 0 index: -1 spectre rotate: false - xy: 1915, 1659 + xy: 293, 614 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 spectre-icon-full rotate: false - xy: 875, 1533 + xy: 423, 744 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 -spectre-icon-large - rotate: false - xy: 991, 523 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -spectre-icon-medium - rotate: false - xy: 635, 185 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -spectre-icon-small - rotate: false - xy: 1653, 780 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 spirit-factory-icon-full rotate: false - xy: 293, 742 + xy: 1471, 1399 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -spirit-factory-icon-large +spore-cluster-icon-full rotate: false - xy: 1091, 623 - size: 48, 48 - orig: 48, 48 + xy: 1753, 1353 + size: 40, 40 + orig: 40, 40 offset: 0, 0 index: -1 -spirit-factory-icon-medium +spore-moss-icon-full rotate: false - xy: 635, 151 + xy: 1375, 683 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -spirit-factory-icon-small +spore-pine-icon-full rotate: false - xy: 1138, 195 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -spore-cluster-icon-large - rotate: false - xy: 1141, 673 + xy: 1561, 1349 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -spore-cluster-icon-medium - rotate: false - xy: 635, 117 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -spore-cluster-icon-small - rotate: false - xy: 1086, 143 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -spore-moss-icon-large - rotate: false - xy: 891, 373 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -spore-moss-icon-small - rotate: false - xy: 1112, 169 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -spore-pine-icon-medium - rotate: false - xy: 635, 83 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -spore-pine-icon-small - rotate: false - xy: 1627, 749 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 spore-press-icon-full rotate: false - xy: 293, 544 + xy: 1867, 1395 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -spore-press-icon-large +sporerocks-icon-full rotate: false - xy: 941, 423 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -spore-press-icon-medium - rotate: false - xy: 635, 49 + xy: 1167, 649 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -spore-press-icon-small +stone-icon-full rotate: false - xy: 1731, 843 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -sporerocks-icon-large - rotate: false - xy: 991, 473 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -sporerocks-icon-small - rotate: false - xy: 1679, 791 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -stone-icon-large - rotate: false - xy: 1041, 523 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -stone-icon-small - rotate: false - xy: 1705, 817 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -surge-tower-icon-large - rotate: false - xy: 1091, 573 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -surge-tower-icon-medium - rotate: false - xy: 635, 15 + xy: 1167, 615 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -surge-tower-icon-small - rotate: false - xy: 1653, 754 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -surge-wall-icon-large - rotate: false - xy: 1141, 623 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -surge-wall-icon-small - rotate: false - xy: 1112, 143 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -surge-wall-large-icon-large - rotate: false - xy: 941, 373 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -surge-wall-large-icon-medium - rotate: false - xy: 669, 261 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -surge-wall-large-icon-small - rotate: false - xy: 1138, 169 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 swarmer rotate: false - xy: 359, 478 + xy: 903, 1353 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 swarmer-icon-full rotate: false - xy: 293, 346 + xy: 969, 1353 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -swarmer-icon-large +tainted-water-icon-full rotate: false - xy: 1041, 473 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -swarmer-icon-medium - rotate: false - xy: 703, 295 + xy: 1167, 581 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -swarmer-icon-small +tar-icon-full rotate: false - xy: 1627, 723 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -tainted-water-icon-large - rotate: false - xy: 1091, 523 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -tainted-water-icon-small - rotate: false - xy: 1757, 843 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -tar-icon-large - rotate: false - xy: 1141, 573 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -tar-icon-small - rotate: false - xy: 1679, 765 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -tau-mech-pad-icon-large - rotate: false - xy: 1091, 473 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -tau-mech-pad-icon-medium - rotate: false - xy: 669, 227 + xy: 1201, 615 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -tau-mech-pad-icon-small +tendrils-icon-full rotate: false - xy: 1705, 791 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -tendrils-icon-large - rotate: false - xy: 1141, 523 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -tendrils-icon-small - rotate: false - xy: 1731, 817 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -thermal-generator-icon-large - rotate: false - xy: 1041, 373 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -thermal-generator-icon-medium - rotate: false - xy: 703, 261 + xy: 1235, 649 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -thermal-generator-icon-small - rotate: false - xy: 1653, 728 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -thermal-pump-icon-large - rotate: false - xy: 1091, 423 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -thermal-pump-icon-medium - rotate: false - xy: 737, 295 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -thermal-pump-icon-small - rotate: false - xy: 1138, 143 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -thorium-reactor-icon-large - rotate: false - xy: 1141, 473 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -thorium-reactor-icon-medium - rotate: false - xy: 669, 193 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -thorium-reactor-icon-small - rotate: false - xy: 1627, 697 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -thorium-wall-icon-large - rotate: false - xy: 1091, 373 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -thorium-wall-icon-small - rotate: false - xy: 1783, 843 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -thorium-wall-large-icon-large - rotate: false - xy: 1141, 423 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -thorium-wall-large-icon-medium - rotate: false - xy: 737, 261 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -thorium-wall-large-icon-small - rotate: false - xy: 1679, 739 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -thruster-icon-large - rotate: false - xy: 1141, 373 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -thruster-icon-medium - rotate: false - xy: 669, 159 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -thruster-icon-small - rotate: false - xy: 1705, 765 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 titan-factory-icon-full rotate: false - xy: 1297, 1251 + xy: 852, 1659 size: 96, 96 orig: 96, 96 offset: 0, 0 index: -1 -titan-factory-icon-large - rotate: false - xy: 841, 323 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -titan-factory-icon-medium - rotate: false - xy: 703, 193 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titan-factory-icon-small - rotate: false - xy: 1731, 791 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -titanium-conveyor-icon-large - rotate: false - xy: 891, 323 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -titanium-conveyor-icon-small - rotate: false - xy: 1757, 817 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -titanium-wall-icon-large - rotate: false - xy: 941, 323 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -titanium-wall-icon-small - rotate: false - xy: 1653, 702 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -titanium-wall-large-icon-large - rotate: false - xy: 991, 323 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -titanium-wall-large-icon-medium - rotate: false - xy: 771, 149 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium-wall-large-icon-small - rotate: false - xy: 1627, 671 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -trident-ship-pad-icon-large - rotate: false - xy: 1041, 323 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -trident-ship-pad-icon-medium - rotate: false - xy: 771, 115 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -trident-ship-pad-icon-small - rotate: false - xy: 1809, 843 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -turbine-generator-icon-large - rotate: false - xy: 1091, 323 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -turbine-generator-icon-medium - rotate: false - xy: 805, 149 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -turbine-generator-icon-small - rotate: false - xy: 1679, 713 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 unit-icon-chaos-array rotate: false - xy: 1135, 1533 + xy: 423, 614 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 unit-icon-crawler rotate: false - xy: 1141, 323 + xy: 1511, 1249 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 unit-icon-dagger rotate: false - xy: 791, 285 + xy: 1561, 1299 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 unit-icon-eradicator rotate: false - xy: 1206, 1923 + xy: 1, 101 size: 152, 124 orig: 152, 124 offset: 0, 0 index: -1 unit-icon-eruptor rotate: false - xy: 359, 82 + xy: 979, 1023 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 unit-icon-fortress rotate: false - xy: 293, 16 + xy: 913, 957 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 unit-icon-titan rotate: false - xy: 359, 16 + xy: 979, 957 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -unloader-icon-large - rotate: false - xy: 841, 273 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -unloader-icon-small - rotate: false - xy: 1705, 739 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -vault-icon-large - rotate: false - xy: 891, 273 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -vault-icon-medium - rotate: false - xy: 805, 115 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -vault-icon-small - rotate: false - xy: 1731, 765 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 water-extractor-icon-full rotate: false - xy: 425, 1006 + xy: 979, 891 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -water-extractor-icon-large +water-icon-full rotate: false - xy: 941, 273 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -water-extractor-icon-medium - rotate: false - xy: 771, 47 + xy: 1197, 513 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 -water-extractor-icon-small - rotate: false - xy: 1757, 791 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -water-icon-large - rotate: false - xy: 991, 273 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -water-icon-small - rotate: false - xy: 1783, 817 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 wave rotate: false - xy: 425, 742 + xy: 979, 759 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 wave-icon-full rotate: false - xy: 425, 676 + xy: 913, 693 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -wave-icon-large +white-tree-dead-icon-full rotate: false - xy: 1041, 273 - size: 48, 48 - orig: 48, 48 + xy: 1, 1405 + size: 320, 320 + orig: 320, 320 offset: 0, 0 index: -1 -wave-icon-medium +white-tree-icon-full rotate: false - xy: 805, 81 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -wave-icon-small - rotate: false - xy: 1653, 676 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -white-tree-dead-icon-large - rotate: false - xy: 1091, 273 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -white-tree-dead-icon-medium - rotate: false - xy: 805, 47 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -white-tree-dead-icon-small - rotate: false - xy: 1627, 645 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -white-tree-icon-large - rotate: false - xy: 1141, 273 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -white-tree-icon-medium - rotate: false - xy: 839, 239 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -white-tree-icon-small - rotate: false - xy: 1835, 843 - size: 24, 24 - orig: 24, 24 + xy: 323, 1727 + size: 320, 320 + orig: 320, 320 offset: 0, 0 index: -1 wraith-factory-icon-full rotate: false - xy: 425, 544 + xy: 1045, 1287 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -wraith-factory-icon-large - rotate: false - xy: 1199, 923 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -wraith-factory-icon-medium - rotate: false - xy: 873, 239 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -wraith-factory-icon-small - rotate: false - xy: 1679, 687 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -item-biomatter - rotate: false - xy: 1403, 867 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 item-blast-compound rotate: false - xy: 1403, 833 + xy: 1212, 1159 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-coal rotate: false - xy: 1403, 799 + xy: 1246, 1159 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-copper rotate: false - xy: 1403, 765 + xy: 1280, 1159 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-graphite rotate: false - xy: 1403, 731 + xy: 1314, 1159 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-lead rotate: false - xy: 1403, 697 + xy: 1348, 1159 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-metaglass rotate: false - xy: 1403, 663 + xy: 1382, 1159 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-phase-fabric rotate: false - xy: 1403, 629 + xy: 1178, 1125 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-plastanium rotate: false - xy: 1403, 595 + xy: 1212, 1125 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-pyratite rotate: false - xy: 1403, 561 + xy: 1246, 1125 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-sand rotate: false - xy: 1403, 527 + xy: 1280, 1125 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-scrap rotate: false - xy: 1403, 493 + xy: 1314, 1125 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-silicon rotate: false - xy: 1403, 459 + xy: 1348, 1125 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-spore-pod rotate: false - xy: 1437, 844 + xy: 1171, 1091 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-surge-alloy rotate: false - xy: 1437, 810 + xy: 1171, 1057 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-thorium rotate: false - xy: 1437, 776 + xy: 1205, 1091 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-titanium rotate: false - xy: 1437, 742 + xy: 1171, 1023 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-cryofluid rotate: false - xy: 1437, 436 + xy: 1171, 989 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-oil rotate: false - xy: 1437, 402 + xy: 1239, 1057 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-slag rotate: false - xy: 1771, 869 + xy: 1273, 1057 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-water rotate: false - xy: 1873, 869 + xy: 1171, 921 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 alpha-mech rotate: false - xy: 549, 971 + xy: 1999, 1411 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 alpha-mech-base rotate: false - xy: 607, 1029 + xy: 1999, 1361 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 alpha-mech-leg rotate: false - xy: 723, 1087 + xy: 979, 527 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 delta-mech rotate: false - xy: 591, 621 + xy: 1029, 262 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 delta-mech-base rotate: false - xy: 591, 571 + xy: 979, 169 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 delta-mech-leg rotate: false - xy: 591, 521 + xy: 1029, 212 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 omega-mech rotate: false - xy: 491, 1079 + xy: 1045, 786 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 omega-mech-armor rotate: false - xy: 858, 1073 + xy: 1676, 1597 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 omega-mech-base rotate: false - xy: 549, 1079 + xy: 1045, 728 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 omega-mech-leg rotate: false - xy: 491, 1021 + xy: 1045, 670 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 tau-mech rotate: false - xy: 549, 1021 + xy: 971, 635 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 tau-mech-base rotate: false - xy: 991, 373 + xy: 1511, 1299 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 tau-mech-leg rotate: false - xy: 1041, 423 + xy: 1611, 1349 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 dart-ship rotate: false - xy: 591, 721 + xy: 979, 219 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 glaive-ship rotate: false - xy: 434, 1146 + xy: 526, 1539 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 javelin-ship rotate: false - xy: 749, 979 + xy: 1161, 1327 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 javelin-ship-shield rotate: false - xy: 741, 879 + xy: 1161, 1277 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 trident-ship rotate: false - xy: 665, 1079 + xy: 971, 577 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 blank rotate: false - xy: 1449, 1034 + xy: 1129, 154 size: 1, 1 orig: 1, 1 offset: 0, 0 index: -1 circle rotate: false - xy: 323, 1758 + xy: 323, 1524 size: 201, 201 orig: 201, 201 offset: 0, 0 index: -1 -clear - rotate: false - xy: 1164, 244 - size: 1, 1 - orig: 1, 1 - offset: 0, 0 - index: -1 shape-3 rotate: false - xy: 425, 413 + xy: 1045, 1156 size: 63, 63 orig: 63, 63 offset: 0, 0 index: -1 -bar - rotate: false - xy: 800, 9 - size: 27, 36 - split: 9, 9, 9, 9 - orig: 27, 36 - offset: 0, 0 - index: -1 -bar-top - rotate: false - xy: 771, 9 - size: 27, 36 - split: 9, 10, 9, 10 - orig: 27, 36 - offset: 0, 0 - index: -1 -button - rotate: false - xy: 1191, 316 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -button-disabled - rotate: false - xy: 786, 1764 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -button-down - rotate: false - xy: 2010, 2020 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -button-edge-1 - rotate: false - xy: 1191, 432 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -button-edge-2 - rotate: false - xy: 824, 1764 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -button-edge-3 - rotate: false - xy: 2010, 1991 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -button-edge-4 - rotate: false - xy: 1191, 403 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -button-over - rotate: false - xy: 2010, 1962 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -button-right - rotate: false - xy: 1191, 345 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -button-right-down - rotate: false - xy: 1191, 374 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -button-right-over - rotate: false - xy: 2010, 1933 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -button-select - rotate: false - xy: 559, 5 - size: 24, 24 - split: 4, 4, 4, 4 - orig: 24, 24 - offset: 0, 0 - index: -1 -check-disabled - rotate: false - xy: 1267, 772 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -check-off - rotate: false - xy: 1267, 738 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -check-on - rotate: false - xy: 1267, 704 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -check-on-disabled - rotate: false - xy: 1267, 670 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -check-on-over - rotate: false - xy: 1267, 636 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -check-over - rotate: false - xy: 1267, 602 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -clear - rotate: false - xy: 1265, 1533 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -content-background - rotate: false - xy: 1325, 1024 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -content-background-locked - rotate: false - xy: 1191, 287 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -content-background-noitems - rotate: false - xy: 1249, 1024 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -content-background-over - rotate: false - xy: 1287, 1024 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -cursor - rotate: false - xy: 317, 1633 - size: 4, 4 - orig: 4, 4 - offset: 0, 0 - index: -1 -discord-banner - rotate: false - xy: 1, 13 - size: 84, 45 - orig: 84, 45 - offset: 0, 0 - index: -1 -empty-sector - rotate: false - xy: 1369, 860 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -icon-crafting - rotate: false - xy: 771, 311 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-defense - rotate: false - xy: 611, 13 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-distribution - rotate: false - xy: 1471, 374 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-effect - rotate: false - xy: 1705, 721 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-liquid - rotate: false - xy: 1470, 1151 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-power - rotate: false - xy: 562, 1889 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-production - rotate: false - xy: 1627, 591 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-turret - rotate: false - xy: 1627, 501 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-units - rotate: false - xy: 1627, 465 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-upgrade - rotate: false - xy: 1627, 429 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -controller-cursor - rotate: false - xy: 1452, 1151 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-about - rotate: false - xy: 1379, 1545 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-add - rotate: false - xy: 1967, 1569 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-admin - rotate: false - xy: 467, 27 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-admin-small - rotate: false - xy: 1653, 1193 - size: 6, 6 - orig: 6, 6 - offset: 0, 0 - index: -1 -icon-areaDelete - rotate: false - xy: 1567, 1208 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-arrow - rotate: false - xy: 1518, 1128 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-arrow-16 - rotate: false - xy: 1518, 1128 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-arrow-down - rotate: false - xy: 1963, 1189 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-arrow-left - rotate: false - xy: 1914, 1057 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-arrow-right - rotate: false - xy: 1, 1 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-arrow-up - rotate: false - xy: 305, 1431 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-back - rotate: false - xy: 526, 1889 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-ban - rotate: false - xy: 1650, 1069 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-break - rotate: false - xy: 2010, 1793 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-cancel - rotate: false - xy: 1431, 1019 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-cancel-2 - rotate: false - xy: 1575, 815 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -icon-chat - rotate: false - xy: 857, 45 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-check - rotate: false - xy: 1499, 996 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-check-2 - rotate: false - xy: 1601, 841 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -icon-copy - rotate: false - xy: 669, 337 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-cursor - rotate: false - xy: 1277, 1533 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-database - rotate: false - xy: 823, 1085 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-database-small - rotate: false - xy: 1567, 1196 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-dev-builds - rotate: false - xy: 1363, 1037 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-diagonal - rotate: false - xy: 1167, 255 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-discord - rotate: false - xy: 467, 11 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-donate - rotate: false - xy: 1666, 1069 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-dots - rotate: false - xy: 839, 1085 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-editor - rotate: false - xy: 1682, 1069 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-egg - rotate: false - xy: 669, 7 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-elevation - rotate: false - xy: 1731, 747 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-eraser - rotate: false - xy: 1757, 773 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-exit - rotate: false - xy: 685, 7 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-file - rotate: false - xy: 1783, 799 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-file-image - rotate: false - xy: 1809, 825 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-file-text - rotate: false - xy: 701, 7 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-fill - rotate: false - xy: 1653, 658 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-floppy - rotate: false - xy: 717, 7 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-floppy-16 - rotate: false - xy: 1627, 627 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-folder - rotate: false - xy: 733, 7 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-folder-parent - rotate: false - xy: 749, 7 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-generated - rotate: false - xy: 641, 405 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -icon-github - rotate: false - xy: 1167, 239 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-google-play - rotate: false - xy: 1164, 223 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-grid - rotate: false - xy: 1861, 851 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-hold - rotate: false - xy: 1926, 1057 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-holdDelete - rotate: false - xy: 13, 1 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-home - rotate: false - xy: 1164, 207 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-host - rotate: false - xy: 1164, 191 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-info - rotate: false - xy: 1164, 175 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-itch.io - rotate: false - xy: 1164, 159 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-item - rotate: false - xy: 305, 1419 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-items-none - rotate: false - xy: 744, 1887 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -icon-line - rotate: false - xy: 2029, 1151 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-link - rotate: false - xy: 1164, 143 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-liquid-small - rotate: false - xy: 1938, 1057 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-load - rotate: false - xy: 1723, 723 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-load-image - rotate: false - xy: 1536, 1128 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-load-map - rotate: false - xy: 544, 1889 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-loading - rotate: false - xy: 771, 293 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-locked - rotate: false - xy: 1705, 703 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-logic - rotate: false - xy: 25, 1 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-map - rotate: false - xy: 1723, 707 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-menu - rotate: false - xy: 305, 1407 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-menu-large - rotate: false - xy: 1827, 825 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-missing - rotate: false - xy: 1950, 1057 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-mission-background - rotate: false - xy: 2029, 1169 - size: 18, 18 - orig: 18, 18 - offset: 0, 0 - index: -1 -icon-mission-battle - rotate: false - xy: 37, 1 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-mission-defense - rotate: false - xy: 49, 1 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-mission-done - rotate: false - xy: 61, 1 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-none - rotate: false - xy: 73, 1 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-paste - rotate: false - xy: 1627, 609 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-pause - rotate: false - xy: 611, 1 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-pencil - rotate: false - xy: 1879, 851 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-pencil-small - rotate: false - xy: 1723, 691 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-pick - rotate: false - xy: 2029, 1133 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-play - rotate: false - xy: 623, 1 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-play-2 - rotate: false - xy: 1749, 749 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-play-custom - rotate: false - xy: 1775, 775 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-players - rotate: false - xy: 857, 33 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-power-requirement - rotate: false - xy: 1369, 554 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -icon-power-small - rotate: false - xy: 498, 1388 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-quit - rotate: false - xy: 1801, 801 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-redo - rotate: false - xy: 2029, 1115 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-refresh - rotate: false - xy: 1863, 835 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-rename - rotate: false - xy: 1879, 835 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-resize - rotate: false - xy: 1627, 573 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-rotate - rotate: false - xy: 1863, 819 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-rotate-arrow - rotate: false - xy: 1879, 819 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-rotate-left - rotate: false - xy: 1645, 624 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-rotate-right - rotate: false - xy: 1645, 608 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-save - rotate: false - xy: 1645, 592 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-save-image - rotate: false - xy: 2029, 1097 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-save-map - rotate: false - xy: 1627, 555 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-settings - rotate: false - xy: 862, 1781 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-spray - rotate: false - xy: 2029, 1079 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-terrain - rotate: false - xy: 1627, 537 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-tools - rotate: false - xy: 1645, 576 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-touch - rotate: false - xy: 2010, 1921 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-touchDelete - rotate: false - xy: 1233, 911 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-trash - rotate: false - xy: 1645, 560 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-trash-16 - rotate: false - xy: 2029, 1061 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-tree - rotate: false - xy: 1627, 519 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-tree-locked - rotate: false - xy: 1369, 520 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -icon-trello - rotate: false - xy: 1645, 544 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-tutorial - rotate: false - xy: 1645, 528 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-undo - rotate: false - xy: 1627, 483 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-unlocked - rotate: false - xy: 1627, 447 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-unlocks - rotate: false - xy: 1645, 512 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-wiki - rotate: false - xy: 1645, 496 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-zone - rotate: false - xy: 1497, 711 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -icon-zone-locked - rotate: false - xy: 219, 1399 - size: 42, 42 - orig: 42, 42 - offset: 0, 0 - index: -1 -icon-zoom - rotate: false - xy: 1627, 411 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-zoom-small - rotate: false - xy: 1645, 480 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -info-banner - rotate: false - xy: 1493, 1220 - size: 84, 45 - orig: 84, 45 - offset: 0, 0 - index: -1 -inventory - rotate: false - xy: 1601, 799 - size: 24, 40 - split: 10, 10, 10, 14 - orig: 24, 40 - offset: 0, 0 - index: -1 -logotext - rotate: false - xy: 1, 1961 - size: 579, 86 - orig: 579, 86 - offset: 0, 0 - index: -1 -pane - rotate: false - xy: 1287, 966 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -pane-2 - rotate: false - xy: 1287, 995 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -scroll - rotate: false - xy: 1653, 832 - size: 24, 35 - split: 10, 10, 6, 5 - orig: 24, 35 - offset: 0, 0 - index: -1 -scroll-horizontal - rotate: false - xy: 807, 1535 - size: 35, 24 - split: 6, 5, 10, 10 - orig: 35, 24 - offset: 0, 0 - index: -1 -scroll-knob-horizontal-black - rotate: false - xy: 744, 1897 - size: 40, 24 - split: 11, 10, 10, 10 - orig: 40, 24 - offset: 0, 0 - index: -1 -scroll-knob-vertical-black - rotate: false - xy: 1627, 827 - size: 24, 40 - split: 10, 10, 6, 10 - orig: 24, 40 - offset: 0, 0 - index: -1 -sector-select - rotate: false - xy: 567, 65 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -selection - rotate: false - xy: 510, 1397 - size: 1, 1 - orig: 1, 1 - offset: 0, 0 - index: -1 -slider - rotate: false - xy: 1449, 1024 - size: 1, 8 - orig: 1, 8 - offset: 0, 0 - index: -1 -slider-knob - rotate: false - xy: 839, 199 - size: 29, 38 - orig: 29, 38 - offset: 0, 0 - index: -1 -slider-knob-down - rotate: false - xy: 839, 159 - size: 29, 38 - orig: 29, 38 - offset: 0, 0 - index: -1 -slider-knob-over - rotate: false - xy: 839, 159 - size: 29, 38 - orig: 29, 38 - offset: 0, 0 - index: -1 -slider-vertical - rotate: false - xy: 1567, 1193 - size: 8, 1 - orig: 8, 1 - offset: 0, 0 - index: -1 -underline - rotate: false - xy: 1325, 928 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -underline-2 - rotate: false - xy: 1287, 937 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -underline-disabled - rotate: false - xy: 1325, 957 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -underline-red - rotate: false - xy: 1287, 908 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -white - rotate: false - xy: 1249, 1068 - size: 3, 3 - orig: 3, 3 - offset: 0, 0 - index: -1 -window-empty - rotate: false - xy: 1467, 305 - size: 27, 61 - split: 8, 8, 44, 11 - orig: 27, 61 - offset: 0, 0 - index: -1 chaos-array rotate: false - xy: 485, 1627 + xy: 163, 773 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 chaos-array-base rotate: false - xy: 656, 1757 + xy: 163, 643 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 chaos-array-leg rotate: false - xy: 615, 1627 + xy: 163, 513 size: 128, 128 orig: 128, 128 offset: 0, 0 index: -1 crawler rotate: false - xy: 907, 1023 + xy: 979, 369 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 crawler-base rotate: false - xy: 957, 1023 + xy: 1029, 412 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 crawler-leg rotate: false - xy: 1057, 1023 + xy: 979, 319 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 dagger rotate: false - xy: 541, 913 + xy: 1029, 362 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 dagger-base rotate: false - xy: 541, 863 + xy: 979, 269 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 dagger-leg rotate: false - xy: 541, 763 + xy: 1029, 312 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +draug + rotate: false + xy: 1029, 162 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 eradicator rotate: false - xy: 744, 1923 + xy: 1496, 1923 size: 152, 124 orig: 152, 124 offset: 0, 0 index: -1 eradicator-base rotate: false - xy: 898, 1923 + xy: 1, 227 size: 152, 124 orig: 152, 124 offset: 0, 0 index: -1 eradicator-leg rotate: false - xy: 1052, 1923 + xy: 1650, 1923 size: 152, 124 orig: 152, 124 offset: 0, 0 index: -1 eruptor rotate: false - xy: 990, 1139 + xy: 525, 54 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 eruptor-base rotate: false - xy: 1056, 1205 + xy: 591, 54 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 eruptor-leg rotate: false - xy: 1122, 1271 + xy: 657, 54 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 fortress rotate: false - xy: 1056, 1139 + xy: 1082, 1617 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 fortress-base rotate: false - xy: 1122, 1205 + xy: 1082, 1551 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 titan-base rotate: false - xy: 1122, 1205 + xy: 1082, 1551 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 fortress-leg rotate: false - xy: 1188, 1271 + xy: 1075, 1485 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 ghoul rotate: false - xy: 1967, 1585 + xy: 219, 1190 size: 72, 72 orig: 72, 72 offset: 0, 0 index: -1 lich rotate: false - xy: 1, 1397 + xy: 1, 1163 size: 216, 240 orig: 216, 240 offset: 0, 0 index: -1 phantom rotate: false - xy: 607, 1079 + xy: 913, 635 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 power-cell rotate: false - xy: 491, 963 + xy: 913, 577 size: 56, 56 orig: 56, 56 offset: 0, 0 index: -1 reaper rotate: false - xy: 1, 1639 + xy: 1, 1727 size: 320, 320 orig: 320, 320 offset: 0, 0 index: -1 revenant rotate: false - xy: 1265, 1545 + xy: 645, 1732 size: 112, 112 orig: 112, 112 offset: 0, 0 index: -1 spirit rotate: false - xy: 1041, 573 + xy: 1461, 1299 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 titan rotate: false - xy: 293, 214 + xy: 913, 1221 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 titan-leg rotate: false - xy: 359, 280 + xy: 979, 1221 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 wraith rotate: false - xy: 1199, 973 + xy: 1661, 1349 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 artillery-equip rotate: false - xy: 491, 805 + xy: 979, 469 size: 48, 56 orig: 48, 56 offset: 0, 0 index: -1 blaster-equip rotate: false - xy: 491, 605 + xy: 1029, 512 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 bomber-equip rotate: false - xy: 491, 555 + xy: 979, 419 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 missiles-equip rotate: false - xy: 491, 555 + xy: 979, 419 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 chain-blaster-equip rotate: false - xy: 773, 1085 + xy: 1029, 462 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 chaos-equip rotate: false - xy: 425, 275 + xy: 1045, 1018 size: 56, 136 orig: 56, 136 offset: 0, 0 index: -1 eradication-equip rotate: false - xy: 204, 1203 + xy: 391, 192 size: 96, 192 orig: 96, 192 offset: 0, 0 index: -1 eruption-equip rotate: false - xy: 641, 763 + xy: 1083, 562 size: 48, 56 orig: 48, 56 offset: 0, 0 index: -1 flakgun-equip rotate: false - xy: 641, 713 + xy: 1079, 512 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 flamethrower-equip rotate: false - xy: 641, 655 + xy: 1079, 454 size: 48, 56 orig: 48, 56 offset: 0, 0 index: -1 heal-blaster-equip rotate: false - xy: 691, 729 + xy: 1079, 404 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 lich-missiles-equip rotate: false - xy: 741, 529 + xy: 1211, 1327 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 reaper-gun-equip rotate: false - xy: 941, 723 + xy: 1361, 1227 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 revenant-missiles-equip rotate: false - xy: 1091, 873 + xy: 1411, 1327 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 shockgun-equip rotate: false - xy: 891, 473 + xy: 1411, 1227 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 swarmer-equip rotate: false - xy: 991, 423 + xy: 1461, 1249 size: 48, 48 orig: 48, 48 offset: 0, 0 @@ -8456,35 +5227,35 @@ blast-mixer-icon-editor index: -1 block-border-editor rotate: false - xy: 361, 103 + xy: 469, 145 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conduit-icon-editor rotate: false - xy: 403, 145 + xy: 603, 399 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 bridge-conveyor-icon-editor rotate: false - xy: 603, 399 + xy: 503, 145 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 char-icon-editor rotate: false - xy: 361, 69 + xy: 637, 399 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-char1 rotate: false - xy: 361, 69 + xy: 637, 399 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -8498,7 +5269,7 @@ clear-editor index: -1 cliffs-icon-editor rotate: false - xy: 437, 145 + xy: 671, 399 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -8512,14 +5283,14 @@ coal-centrifuge-icon-editor index: -1 combustion-generator-icon-editor rotate: false - xy: 637, 399 + xy: 295, 13 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 conduit-icon-editor rotate: false - xy: 471, 145 + xy: 329, 13 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -8533,14 +5304,14 @@ container-icon-editor index: -1 conveyor-icon-editor rotate: false - xy: 671, 399 + xy: 427, 103 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 copper-wall-icon-editor rotate: false - xy: 505, 145 + xy: 537, 145 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -8575,14 +5346,14 @@ core-shard-icon-editor index: -1 craters-icon-editor rotate: false - xy: 295, 13 + xy: 363, 29 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-craters1 rotate: false - xy: 295, 13 + xy: 363, 29 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -8624,7 +5395,7 @@ dagger-factory-icon-editor index: -1 dark-metal-icon-editor rotate: false - xy: 329, 13 + xy: 411, 69 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -8811,6 +5582,13 @@ door-large-icon-editor orig: 64, 64 offset: 0, 0 index: -1 +draug-factory-icon-editor + rotate: false + xy: 1537, 861 + size: 64, 64 + orig: 64, 64 + offset: 0, 0 + index: -1 dunerocks-icon-editor rotate: false xy: 589, 263 @@ -8925,644 +5703,644 @@ editor-holostone2 index: -1 editor-holostone3 rotate: false - xy: 539, 145 + xy: 571, 161 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-hotrock1 rotate: false - xy: 573, 161 + xy: 605, 161 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 hotrock-icon-editor rotate: false - xy: 573, 161 + xy: 605, 161 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-hotrock2 rotate: false - xy: 607, 161 + xy: 639, 161 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-hotrock3 rotate: false - xy: 641, 161 + xy: 673, 161 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ice-snow1 rotate: false - xy: 675, 161 + xy: 529, 111 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ice-snow-icon-editor rotate: false - xy: 675, 161 + xy: 529, 111 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ice-snow2 rotate: false - xy: 675, 127 + xy: 571, 127 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ice-snow3 rotate: false - xy: 691, 331 + xy: 605, 127 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ice1 rotate: false - xy: 573, 127 + xy: 445, 69 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ice-icon-editor rotate: false - xy: 573, 127 + xy: 445, 69 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ice2 rotate: false - xy: 607, 127 + xy: 461, 103 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ice3 rotate: false - xy: 641, 127 + xy: 495, 111 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ignarock1 rotate: false - xy: 691, 297 + xy: 639, 127 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ignarock-icon-editor rotate: false - xy: 691, 297 + xy: 639, 127 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ignarock2 rotate: false - xy: 691, 263 + xy: 673, 127 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ignarock3 rotate: false - xy: 691, 229 + xy: 479, 69 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-magmarock1 rotate: false - xy: 691, 195 + xy: 513, 77 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 magmarock-icon-editor rotate: false - xy: 691, 195 + xy: 513, 77 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-magmarock2 rotate: false - xy: 709, 161 + xy: 547, 77 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-magmarock3 rotate: false - xy: 709, 127 + xy: 581, 93 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-metal-floor rotate: false - xy: 705, 399 + xy: 615, 93 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 metal-floor-icon-editor rotate: false - xy: 705, 399 + xy: 615, 93 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-metal-floor-2 rotate: false - xy: 705, 365 + xy: 649, 93 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 metal-floor-2-icon-editor rotate: false - xy: 705, 365 + xy: 649, 93 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-metal-floor-3 rotate: false - xy: 725, 331 + xy: 683, 93 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 metal-floor-3-icon-editor rotate: false - xy: 725, 331 + xy: 683, 93 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-metal-floor-5 rotate: false - xy: 725, 297 + xy: 581, 59 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 metal-floor-5-icon-editor rotate: false - xy: 725, 297 + xy: 581, 59 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-metal-floor-damaged1 rotate: false - xy: 725, 263 + xy: 615, 59 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 metal-floor-damaged-icon-editor rotate: false - xy: 725, 263 + xy: 615, 59 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-metal-floor-damaged2 rotate: false - xy: 725, 229 + xy: 649, 59 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-metal-floor-damaged3 rotate: false - xy: 725, 195 + xy: 683, 59 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-moss1 rotate: false - xy: 743, 161 + xy: 691, 331 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 moss-icon-editor rotate: false - xy: 743, 161 + xy: 691, 331 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-moss2 rotate: false - xy: 743, 127 + xy: 691, 297 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-moss3 rotate: false - xy: 363, 35 + xy: 691, 263 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-coal1 rotate: false - xy: 363, 1 + xy: 691, 229 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-coal2 rotate: false - xy: 403, 111 + xy: 691, 195 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-coal3 rotate: false - xy: 437, 111 + xy: 707, 161 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-copper1 rotate: false - xy: 471, 111 + xy: 707, 127 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-copper2 rotate: false - xy: 505, 111 + xy: 717, 93 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-copper3 rotate: false - xy: 539, 111 + xy: 717, 59 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-lead1 rotate: false - xy: 395, 77 + xy: 397, 29 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-lead2 rotate: false - xy: 429, 77 + xy: 431, 35 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-lead3 rotate: false - xy: 463, 77 + xy: 431, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-scrap1 rotate: false - xy: 497, 77 + xy: 465, 35 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-scrap2 rotate: false - xy: 531, 77 + xy: 465, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-scrap3 rotate: false - xy: 397, 43 + xy: 499, 35 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-thorium1 rotate: false - xy: 397, 9 + xy: 499, 1 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-thorium2 rotate: false - xy: 431, 43 + xy: 533, 43 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-thorium3 rotate: false - xy: 431, 9 + xy: 533, 9 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-titanium1 rotate: false - xy: 465, 43 + xy: 567, 25 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-titanium2 rotate: false - xy: 465, 9 + xy: 601, 25 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-ore-titanium3 rotate: false - xy: 499, 43 + xy: 635, 25 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-pebbles1 rotate: false - xy: 499, 9 + xy: 669, 25 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-pebbles2 rotate: false - xy: 533, 43 + xy: 703, 25 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-pebbles3 rotate: false - xy: 533, 9 + xy: 737, 25 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-salt rotate: false - xy: 573, 93 + xy: 705, 399 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 salt-icon-editor rotate: false - xy: 573, 93 + xy: 705, 399 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-sand-water rotate: false - xy: 709, 93 + xy: 725, 263 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 sand-water-icon-editor rotate: false - xy: 709, 93 + xy: 725, 263 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-sand1 rotate: false - xy: 607, 93 + xy: 705, 365 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 sand-icon-editor rotate: false - xy: 607, 93 + xy: 705, 365 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-sand2 rotate: false - xy: 641, 93 + xy: 725, 331 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-sand3 rotate: false - xy: 675, 93 + xy: 725, 297 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-shale1 rotate: false - xy: 743, 93 + xy: 725, 229 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 shale-icon-editor rotate: false - xy: 743, 93 + xy: 725, 229 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-shale2 rotate: false - xy: 567, 59 + xy: 725, 195 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-shale3 rotate: false - xy: 567, 25 + xy: 741, 161 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-snow1 rotate: false - xy: 601, 59 + xy: 741, 127 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 snow-icon-editor rotate: false - xy: 601, 59 + xy: 741, 127 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-snow2 rotate: false - xy: 601, 25 + xy: 751, 93 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-snow3 rotate: false - xy: 635, 59 + xy: 751, 59 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-spawn rotate: false - xy: 635, 25 + xy: 771, 25 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-spore-moss1 rotate: false - xy: 669, 59 + xy: 733, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 spore-moss-icon-editor rotate: false - xy: 669, 59 + xy: 733, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-spore-moss2 rotate: false - xy: 669, 25 + xy: 767, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-spore-moss3 rotate: false - xy: 703, 59 + xy: 801, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-stone1 rotate: false - xy: 703, 25 + xy: 835, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 stone-icon-editor rotate: false - xy: 703, 25 + xy: 835, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-stone2 rotate: false - xy: 737, 59 + xy: 869, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-stone3 rotate: false - xy: 737, 25 + xy: 903, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-tainted-water rotate: false - xy: 771, 59 + xy: 937, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 tainted-water-icon-editor rotate: false - xy: 771, 59 + xy: 937, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-tar rotate: false - xy: 771, 25 + xy: 971, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 tar-icon-editor rotate: false - xy: 771, 25 + xy: 971, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-tendrils1 rotate: false - xy: 733, 827 + xy: 1005, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-tendrils2 rotate: false - xy: 767, 827 + xy: 1039, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-tendrils3 rotate: false - xy: 801, 827 + xy: 1073, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 editor-water rotate: false - xy: 835, 827 + xy: 1107, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 water-icon-editor rotate: false - xy: 835, 827 + xy: 1107, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -9604,21 +6382,21 @@ glaive-ship-pad-icon-editor index: -1 graphite-press-icon-editor rotate: false - xy: 1537, 861 + xy: 1603, 861 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 hail-icon-editor rotate: false - xy: 869, 827 + xy: 1141, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 icerocks-icon-editor rotate: false - xy: 903, 827 + xy: 1175, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -9632,49 +6410,49 @@ impact-reactor-icon-editor index: -1 incinerator-icon-editor rotate: false - xy: 937, 827 + xy: 1209, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-source-icon-editor rotate: false - xy: 971, 827 + xy: 1243, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 item-void-icon-editor rotate: false - xy: 1005, 827 + xy: 1277, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 javelin-ship-pad-icon-editor rotate: false - xy: 1603, 861 + xy: 1669, 861 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 junction-icon-editor rotate: false - xy: 1039, 827 + xy: 1311, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 kiln-icon-editor rotate: false - xy: 1669, 861 + xy: 1735, 861 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 lancer-icon-editor rotate: false - xy: 1735, 861 + xy: 1801, 861 size: 64, 64 orig: 64, 64 offset: 0, 0 @@ -9702,21 +6480,21 @@ launch-pad-large-icon-editor index: -1 liquid-junction-icon-editor rotate: false - xy: 1073, 827 + xy: 1345, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-router-icon-editor rotate: false - xy: 1107, 827 + xy: 1379, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 liquid-source-icon-editor rotate: false - xy: 1141, 827 + xy: 1413, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -9737,14 +6515,14 @@ mass-driver-icon-editor index: -1 mechanical-drill-icon-editor rotate: false - xy: 1801, 861 + xy: 1867, 861 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 mechanical-pump-icon-editor rotate: false - xy: 1175, 827 + xy: 1447, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -9758,21 +6536,21 @@ meltdown-icon-editor index: -1 melter-icon-editor rotate: false - xy: 1209, 827 + xy: 1481, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 mend-projector-icon-editor rotate: false - xy: 1867, 861 + xy: 1933, 861 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 mender-icon-editor rotate: false - xy: 1243, 827 + xy: 1515, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -9800,63 +6578,63 @@ omega-mech-pad-icon-editor index: -1 overdrive-projector-icon-editor rotate: false - xy: 1933, 861 + xy: 485, 829 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 overflow-gate-icon-editor rotate: false - xy: 1277, 827 + xy: 1549, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pebbles-icon-editor rotate: false - xy: 1311, 827 + xy: 1583, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phantom-factory-icon-editor rotate: false - xy: 485, 829 + xy: 551, 829 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 phase-conduit-icon-editor rotate: false - xy: 1345, 827 + xy: 1617, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-conveyor-icon-editor rotate: false - xy: 1379, 827 + xy: 1651, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-wall-icon-editor rotate: false - xy: 1413, 827 + xy: 1685, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 phase-wall-large-icon-editor rotate: false - xy: 551, 829 + xy: 617, 829 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 phase-weaver-icon-editor rotate: false - xy: 617, 829 + xy: 453, 763 size: 64, 64 orig: 64, 64 offset: 0, 0 @@ -9870,70 +6648,70 @@ pine-icon-editor index: -1 plastanium-compressor-icon-editor rotate: false - xy: 453, 763 + xy: 519, 763 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 pneumatic-drill-icon-editor rotate: false - xy: 519, 763 + xy: 453, 697 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 power-node-icon-editor rotate: false - xy: 1447, 827 + xy: 1719, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 power-node-large-icon-editor rotate: false - xy: 453, 697 + xy: 519, 697 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 power-source-icon-editor rotate: false - xy: 1481, 827 + xy: 1753, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 power-void-icon-editor rotate: false - xy: 1515, 827 + xy: 1787, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulse-conduit-icon-editor rotate: false - xy: 1549, 827 + xy: 1821, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pulverizer-icon-editor rotate: false - xy: 1583, 827 + xy: 1855, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pyratite-mixer-icon-editor rotate: false - xy: 519, 697 + xy: 585, 763 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 repair-point-icon-editor rotate: false - xy: 1617, 827 + xy: 1889, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -9961,63 +6739,70 @@ rock-icon-editor index: -1 rocks-icon-editor rotate: false - xy: 1651, 827 + xy: 1923, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 rotary-pump-icon-editor rotate: false - xy: 585, 763 + xy: 453, 631 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 router-icon-editor rotate: false - xy: 1685, 827 + xy: 1957, 827 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 rtg-generator-icon-editor rotate: false - xy: 453, 631 + xy: 519, 631 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 saltrocks-icon-editor rotate: false - xy: 1719, 827 + xy: 717, 793 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 salvo-icon-editor rotate: false - xy: 519, 631 + xy: 585, 697 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 +sand-boulder-icon-editor + rotate: false + xy: 717, 759 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 sandrocks-icon-editor rotate: false - xy: 1753, 827 + xy: 751, 793 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scatter-icon-editor rotate: false - xy: 585, 697 + xy: 453, 565 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 scorch-icon-editor rotate: false - xy: 1787, 827 + xy: 785, 793 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -10038,77 +6823,84 @@ scrap-wall-huge-icon-editor index: -1 scrap-wall-icon-editor rotate: false - xy: 1821, 827 + xy: 717, 725 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scrap-wall-large-icon-editor rotate: false - xy: 453, 565 + xy: 519, 565 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 separator-icon-editor rotate: false - xy: 519, 565 + xy: 585, 631 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 shale-boulder-icon-editor rotate: false - xy: 1855, 827 + xy: 751, 759 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 shalerocks-icon-editor rotate: false - xy: 1889, 827 + xy: 785, 759 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 shock-mine-icon-editor rotate: false - xy: 1923, 827 + xy: 819, 793 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 shrubs-icon-editor rotate: false - xy: 1957, 827 + xy: 717, 691 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 silicon-smelter-icon-editor rotate: false - xy: 585, 631 + xy: 453, 499 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 -snowrock-icon-editor +snow-pine-icon-editor rotate: false xy: 519, 383 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 +snowrock-icon-editor + rotate: false + xy: 683, 845 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 snowrocks-icon-editor rotate: false - xy: 717, 793 + xy: 751, 725 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 solar-panel-icon-editor rotate: false - xy: 717, 759 + xy: 785, 725 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -10122,14 +6914,14 @@ solar-panel-large-icon-editor index: -1 sorter-icon-editor rotate: false - xy: 751, 793 + xy: 819, 759 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 spawn-icon-editor rotate: false - xy: 717, 725 + xy: 853, 793 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -10143,84 +6935,84 @@ spectre-icon-editor index: -1 spirit-factory-icon-editor rotate: false - xy: 453, 499 + xy: 519, 499 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 spore-cluster-icon-editor rotate: false - xy: 361, 137 + xy: 427, 137 size: 40, 40 orig: 40, 40 offset: 0, 0 index: -1 spore-pine-icon-editor rotate: false - xy: 683, 845 + xy: 361, 63 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 spore-press-icon-editor rotate: false - xy: 519, 499 + xy: 585, 565 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 sporerocks-icon-editor rotate: false - xy: 785, 793 + xy: 717, 657 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 surge-tower-icon-editor rotate: false - xy: 585, 565 + xy: 585, 499 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 surge-wall-icon-editor rotate: false - xy: 751, 759 + xy: 751, 691 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 surge-wall-large-icon-editor rotate: false - xy: 585, 499 + xy: 519, 433 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 swarmer-icon-editor rotate: false - xy: 519, 433 + xy: 585, 433 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 tau-mech-pad-icon-editor rotate: false - xy: 585, 433 + xy: 651, 763 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 tendrils-icon-editor rotate: false - xy: 717, 691 + xy: 785, 691 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 thermal-generator-icon-editor rotate: false - xy: 651, 763 + xy: 651, 697 size: 64, 64 orig: 64, 64 offset: 0, 0 @@ -10241,14 +7033,14 @@ thorium-reactor-icon-editor index: -1 thorium-wall-icon-editor rotate: false - xy: 819, 793 + xy: 819, 725 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 thorium-wall-large-icon-editor rotate: false - xy: 651, 697 + xy: 651, 631 size: 64, 64 orig: 64, 64 offset: 0, 0 @@ -10269,42 +7061,42 @@ titan-factory-icon-editor index: -1 titanium-conveyor-icon-editor rotate: false - xy: 785, 759 + xy: 853, 759 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-wall-icon-editor rotate: false - xy: 751, 725 + xy: 887, 793 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium-wall-large-icon-editor rotate: false - xy: 651, 631 + xy: 651, 565 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 trident-ship-pad-icon-editor rotate: false - xy: 651, 565 + xy: 651, 499 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 turbine-generator-icon-editor rotate: false - xy: 651, 499 + xy: 651, 433 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 unloader-icon-editor rotate: false - xy: 717, 657 + xy: 717, 623 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -10318,14 +7110,14 @@ vault-icon-editor index: -1 water-extractor-icon-editor rotate: false - xy: 651, 433 + xy: 295, 113 size: 64, 64 orig: 64, 64 offset: 0, 0 index: -1 wave-icon-editor rotate: false - xy: 295, 113 + xy: 295, 47 size: 64, 64 orig: 64, 64 offset: 0, 0 @@ -10346,7 +7138,7 @@ white-tree-icon-editor index: -1 wraith-factory-icon-editor rotate: false - xy: 295, 47 + xy: 361, 113 size: 64, 64 orig: 64, 64 offset: 0, 0 @@ -10359,7 +7151,7 @@ filter: Nearest,Nearest repeat: none char1 rotate: false - xy: 1775, 479 + xy: 1825, 479 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -10380,7 +7172,7 @@ char3 index: -1 cliffs1 rotate: false - xy: 1809, 479 + xy: 1859, 479 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -10394,7 +7186,7 @@ coal1 index: -1 coal2 rotate: false - xy: 1843, 479 + xy: 1893, 479 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -10408,7 +7200,7 @@ coal3 index: -1 copper1 rotate: false - xy: 1877, 479 + xy: 1927, 479 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -10422,7 +7214,7 @@ copper2 index: -1 copper3 rotate: false - xy: 1911, 479 + xy: 1961, 479 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -10436,7 +7228,7 @@ craters1 index: -1 craters2 rotate: false - xy: 1945, 479 + xy: 1995, 479 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -10450,21 +7242,21 @@ craters3 index: -1 craters4 rotate: false - xy: 1979, 479 + xy: 553, 59 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 craters5 rotate: false - xy: 553, 59 + xy: 1429, 217 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 craters6 rotate: false - xy: 2013, 479 + xy: 1495, 283 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -10478,21 +7270,21 @@ dark-metal-large index: -1 dark-metal1 rotate: false - xy: 1429, 217 + xy: 1627, 347 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 dark-metal2 rotate: false - xy: 1495, 283 + xy: 1463, 217 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 dark-panel-1 rotate: false - xy: 1627, 347 + xy: 645, 185 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -10506,7 +7298,7 @@ dark-panel-1-edge index: -1 dark-panel-2 rotate: false - xy: 1463, 217 + xy: 679, 185 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -10520,7 +7312,7 @@ dark-panel-2-edge index: -1 dark-panel-3 rotate: false - xy: 645, 185 + xy: 713, 185 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -10534,7 +7326,7 @@ dark-panel-3-edge index: -1 dark-panel-4 rotate: false - xy: 679, 185 + xy: 747, 185 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -10548,7 +7340,7 @@ dark-panel-4-edge index: -1 dark-panel-5 rotate: false - xy: 713, 185 + xy: 781, 185 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -10562,7 +7354,7 @@ dark-panel-5-edge index: -1 dark-panel-6 rotate: false - xy: 747, 185 + xy: 815, 185 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -10583,7 +7375,7 @@ darksand-edge index: -1 darksand-tainted-water rotate: false - xy: 883, 185 + xy: 951, 185 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -10597,7 +7389,7 @@ darksand-tainted-water-edge index: -1 darksand-water rotate: false - xy: 917, 185 + xy: 985, 185 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -10611,28 +7403,28 @@ darksand-water-edge index: -1 darksand1 rotate: false - xy: 781, 185 + xy: 849, 185 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 darksand2 rotate: false - xy: 815, 185 + xy: 883, 185 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 darksand3 rotate: false - xy: 849, 185 + xy: 917, 185 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 deepwater rotate: false - xy: 951, 185 + xy: 1019, 185 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -10653,21 +7445,21 @@ dunerocks-large index: -1 dunerocks1 rotate: false - xy: 985, 185 + xy: 1053, 185 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 dunerocks2 rotate: false - xy: 1019, 185 + xy: 1087, 185 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 edge rotate: false - xy: 1053, 185 + xy: 1121, 185 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -10681,7 +7473,7 @@ edge-stencil index: -1 edgier rotate: false - xy: 1087, 185 + xy: 1155, 185 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -10695,21 +7487,21 @@ grass-edge index: -1 grass1 rotate: false - xy: 1121, 185 + xy: 1189, 185 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 grass2 rotate: false - xy: 1155, 185 + xy: 1223, 185 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 grass3 rotate: false - xy: 1189, 185 + xy: 1257, 185 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -10723,42 +7515,42 @@ holostone-edge index: -1 holostone1 rotate: false - xy: 1223, 185 + xy: 1291, 185 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 holostone2 rotate: false - xy: 1257, 185 + xy: 1325, 185 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 holostone3 rotate: false - xy: 1291, 185 + xy: 1359, 185 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 hotrock1 rotate: false - xy: 1325, 185 + xy: 1393, 185 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 hotrock2 rotate: false - xy: 1359, 185 + xy: 1427, 183 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 hotrock3 rotate: false - xy: 1393, 185 + xy: 1461, 183 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -10779,42 +7571,42 @@ ice-snow-edge index: -1 ice-snow1 rotate: false - xy: 673, 151 + xy: 741, 151 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ice-snow2 rotate: false - xy: 707, 151 + xy: 775, 151 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ice-snow3 rotate: false - xy: 741, 151 + xy: 809, 151 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ice1 rotate: false - xy: 1427, 183 + xy: 639, 151 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ice2 rotate: false - xy: 1461, 183 + xy: 673, 151 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ice3 rotate: false - xy: 639, 151 + xy: 707, 151 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -10828,14 +7620,14 @@ icerocks-large index: -1 icerocks1 rotate: false - xy: 775, 151 + xy: 843, 151 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 icerocks2 rotate: false - xy: 809, 151 + xy: 877, 151 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -10849,77 +7641,77 @@ ignarock-edge index: -1 ignarock1 rotate: false - xy: 843, 151 + xy: 911, 151 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ignarock2 rotate: false - xy: 877, 151 + xy: 945, 151 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ignarock3 rotate: false - xy: 911, 151 + xy: 979, 151 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 lead1 rotate: false - xy: 945, 151 + xy: 1013, 151 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 lead2 rotate: false - xy: 979, 151 + xy: 1047, 151 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 lead3 rotate: false - xy: 1013, 151 + xy: 1081, 151 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 magmarock1 rotate: false - xy: 1047, 151 + xy: 1115, 151 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 magmarock2 rotate: false - xy: 1081, 151 + xy: 1149, 151 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 magmarock3 rotate: false - xy: 1115, 151 + xy: 1183, 151 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 metal-floor rotate: false - xy: 1149, 151 + xy: 1217, 151 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 metal-floor-2 rotate: false - xy: 1183, 151 + xy: 1251, 151 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -10933,7 +7725,7 @@ metal-floor-2-edge index: -1 metal-floor-3 rotate: false - xy: 1217, 151 + xy: 1285, 151 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -10947,7 +7739,7 @@ metal-floor-3-edge index: -1 metal-floor-5 rotate: false - xy: 1251, 151 + xy: 1319, 151 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -10968,21 +7760,21 @@ metal-floor-damaged-edge index: -1 metal-floor-damaged1 rotate: false - xy: 1285, 151 + xy: 1353, 151 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 metal-floor-damaged2 rotate: false - xy: 1319, 151 + xy: 1387, 151 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 metal-floor-damaged3 rotate: false - xy: 1353, 151 + xy: 1421, 149 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -11003,168 +7795,168 @@ moss-edge index: -1 moss1 rotate: false - xy: 1387, 151 + xy: 1455, 149 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 moss2 rotate: false - xy: 1421, 149 + xy: 1529, 297 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 moss3 rotate: false - xy: 1455, 149 + xy: 1563, 297 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-coal1 rotate: false - xy: 1529, 297 + xy: 1597, 297 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-coal2 rotate: false - xy: 1563, 297 + xy: 349, 25 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-coal3 rotate: false - xy: 1597, 297 + xy: 383, 25 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-copper1 rotate: false - xy: 349, 25 + xy: 417, 25 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-copper2 rotate: false - xy: 383, 25 + xy: 451, 25 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-copper3 rotate: false - xy: 417, 25 + xy: 485, 25 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-lead1 rotate: false - xy: 451, 25 + xy: 519, 25 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-lead2 rotate: false - xy: 485, 25 + xy: 553, 25 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-lead3 rotate: false - xy: 519, 25 + xy: 1661, 363 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-scrap1 rotate: false - xy: 553, 25 + xy: 1709, 413 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-scrap2 rotate: false - xy: 1661, 363 + xy: 1743, 429 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-scrap3 rotate: false - xy: 1709, 413 + xy: 1777, 429 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-thorium1 rotate: false - xy: 1775, 445 + xy: 1825, 445 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-thorium2 rotate: false - xy: 1809, 445 + xy: 1859, 445 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-thorium3 rotate: false - xy: 1843, 445 + xy: 1893, 445 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-titanium1 rotate: false - xy: 1877, 445 + xy: 1927, 445 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-titanium2 rotate: false - xy: 1911, 445 + xy: 1961, 445 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 ore-titanium3 rotate: false - xy: 1945, 445 + xy: 1995, 445 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pebbles1 rotate: false - xy: 1979, 445 + xy: 1661, 329 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pebbles2 rotate: false - xy: 2013, 445 + xy: 1709, 379 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 pebbles3 rotate: false - xy: 1661, 329 + xy: 1743, 395 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -11199,21 +7991,21 @@ rocks-large index: -1 rocks1 rotate: false - xy: 1709, 379 + xy: 1777, 395 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 rocks2 rotate: false - xy: 1695, 345 + xy: 1811, 411 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 salt rotate: false - xy: 1695, 311 + xy: 1845, 411 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -11234,14 +8026,28 @@ saltrocks-large index: -1 saltrocks1 rotate: false - xy: 1529, 263 + xy: 1879, 411 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 saltrocks2 rotate: false - xy: 1563, 263 + xy: 1913, 411 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sand-boulder1 + rotate: false + xy: 1695, 345 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sand-boulder2 + rotate: false + xy: 1743, 361 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -11255,7 +8061,7 @@ sand-edge index: -1 sand-water rotate: false - xy: 639, 117 + xy: 1777, 361 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -11269,21 +8075,21 @@ sand-water-edge index: -1 sand1 rotate: false - xy: 1597, 263 + xy: 1947, 411 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 sand2 rotate: false - xy: 1729, 345 + xy: 1981, 411 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 sand3 rotate: false - xy: 1729, 311 + xy: 2015, 411 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -11297,49 +8103,49 @@ sandrocks-large index: -1 sandrocks1 rotate: false - xy: 673, 117 + xy: 1811, 377 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 sandrocks2 rotate: false - xy: 707, 117 + xy: 1845, 377 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scrap1 rotate: false - xy: 741, 117 + xy: 1879, 377 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scrap2 rotate: false - xy: 775, 117 + xy: 1913, 377 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 scrap3 rotate: false - xy: 809, 117 + xy: 1947, 377 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 shale-boulder1 rotate: false - xy: 945, 117 + xy: 1729, 327 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 shale-boulder2 rotate: false - xy: 979, 117 + xy: 1763, 327 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -11353,21 +8159,21 @@ shale-edge index: -1 shale1 rotate: false - xy: 843, 117 + xy: 1981, 377 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 shale2 rotate: false - xy: 877, 117 + xy: 2015, 377 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 shale3 rotate: false - xy: 911, 117 + xy: 1695, 311 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -11381,14 +8187,14 @@ shalerocks-large index: -1 shalerocks1 rotate: false - xy: 1013, 117 + xy: 1811, 343 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 shalerocks2 rotate: false - xy: 1047, 117 + xy: 1845, 343 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -11402,14 +8208,14 @@ shrubs-large index: -1 shrubs1 rotate: false - xy: 1081, 117 + xy: 1879, 343 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 shrubs2 rotate: false - xy: 1115, 117 + xy: 1913, 343 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -11421,41 +8227,48 @@ snow-edge orig: 96, 96 offset: 0, 0 index: -1 -snow1 - rotate: false - xy: 1149, 117 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -snow2 - rotate: false - xy: 1183, 117 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -snow3 - rotate: false - xy: 1217, 117 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -snowrock1 +snow-pine rotate: false xy: 1725, 463 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 -snowrock2 +snow1 + rotate: false + xy: 1947, 343 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +snow2 + rotate: false + xy: 1981, 343 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +snow3 + rotate: false + xy: 2015, 343 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +snowrock1 rotate: false xy: 265, 43 size: 48, 48 orig: 48, 48 offset: 0, 0 index: -1 +snowrock2 + rotate: false + xy: 1577, 331 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 snowrocks-large rotate: false xy: 1659, 447 @@ -11465,21 +8278,21 @@ snowrocks-large index: -1 snowrocks1 rotate: false - xy: 1251, 117 + xy: 1729, 293 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 snowrocks2 rotate: false - xy: 1285, 117 + xy: 1763, 293 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 spawn rotate: false - xy: 1319, 117 + xy: 1797, 309 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -11514,28 +8327,28 @@ spore-moss-edge index: -1 spore-moss1 rotate: false - xy: 1353, 117 + xy: 1831, 309 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 spore-moss2 rotate: false - xy: 1387, 117 + xy: 1865, 309 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 spore-moss3 rotate: false - xy: 1421, 115 + xy: 1899, 309 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 spore-pine rotate: false - xy: 1577, 331 + xy: 1775, 463 size: 48, 48 orig: 48, 48 offset: 0, 0 @@ -11549,14 +8362,14 @@ sporerocks-large index: -1 sporerocks1 rotate: false - xy: 1455, 115 + xy: 1933, 309 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 sporerocks2 rotate: false - xy: 631, 83 + xy: 1967, 309 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -11570,28 +8383,28 @@ stone-edge index: -1 stone1 rotate: false - xy: 665, 83 + xy: 2001, 309 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 stone2 rotate: false - xy: 699, 83 + xy: 1797, 275 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 stone3 rotate: false - xy: 733, 83 + xy: 1831, 275 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 tainted-water rotate: false - xy: 767, 83 + xy: 1865, 275 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -11605,7 +8418,7 @@ tainted-water-edge index: -1 tar rotate: false - xy: 801, 83 + xy: 1899, 275 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -11619,70 +8432,70 @@ tar-edge index: -1 tendrils1 rotate: false - xy: 835, 83 + xy: 1933, 275 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 tendrils2 rotate: false - xy: 869, 83 + xy: 1967, 275 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 tendrils3 rotate: false - xy: 903, 83 + xy: 2001, 275 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 thorium1 rotate: false - xy: 937, 83 + xy: 1529, 263 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 thorium2 rotate: false - xy: 971, 83 + xy: 1563, 263 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 thorium3 rotate: false - xy: 1005, 83 + xy: 1597, 263 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium1 rotate: false - xy: 1039, 83 + xy: 639, 117 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium2 rotate: false - xy: 1073, 83 + xy: 673, 117 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 titanium3 rotate: false - xy: 1107, 83 + xy: 707, 117 size: 32, 32 orig: 32, 32 offset: 0, 0 index: -1 water rotate: false - xy: 1141, 83 + xy: 741, 117 size: 32, 32 orig: 32, 32 offset: 0, 0 @@ -11708,3 +8521,6372 @@ white-tree-dead orig: 320, 320 offset: 0, 0 index: -1 + +sprites4.png +size: 2048,1024 +format: RGBA8888 +filter: Nearest,Nearest +repeat: none +alloy-smelter-icon-large + rotate: false + xy: 87, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +alloy-smelter-icon-medium + rotate: false + xy: 351, 180 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +alloy-smelter-icon-small + rotate: false + xy: 2023, 794 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +arc-icon-large + rotate: false + xy: 1, 878 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +arc-icon-medium + rotate: false + xy: 127, 38 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +arc-icon-small + rotate: false + xy: 365, 43 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +bar + rotate: false + xy: 487, 85 + size: 27, 36 + split: 9, 9, 9, 9 + orig: 27, 36 + offset: 0, 0 + index: -1 +bar-top + rotate: false + xy: 458, 85 + size: 27, 36 + split: 9, 10, 9, 10 + orig: 27, 36 + offset: 0, 0 + index: -1 +battery-icon-large + rotate: false + xy: 137, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +battery-icon-medium + rotate: false + xy: 161, 38 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +battery-icon-small + rotate: false + xy: 516, 79 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +battery-large-icon-large + rotate: false + xy: 1, 828 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +battery-large-icon-medium + rotate: false + xy: 195, 38 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +battery-large-icon-small + rotate: false + xy: 396, 57 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +blast-drill-icon-large + rotate: false + xy: 187, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +blast-drill-icon-medium + rotate: false + xy: 1076, 888 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +blast-drill-icon-small + rotate: false + xy: 422, 57 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +blast-mixer-icon-large + rotate: false + xy: 1, 778 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +blast-mixer-icon-medium + rotate: false + xy: 1110, 888 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +blast-mixer-icon-small + rotate: false + xy: 391, 31 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +bridge-conduit-icon-large + rotate: false + xy: 237, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +bridge-conduit-icon-medium + rotate: false + xy: 1144, 888 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +bridge-conduit-icon-small + rotate: false + xy: 417, 31 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +bridge-conveyor-icon-large + rotate: false + xy: 1, 728 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +bridge-conveyor-icon-medium + rotate: false + xy: 1178, 888 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +bridge-conveyor-icon-small + rotate: false + xy: 391, 5 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +button + rotate: false + xy: 851, 743 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +button-disabled + rotate: false + xy: 51, 43 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +button-down + rotate: false + xy: 351, 243 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +button-edge-1 + rotate: false + xy: 401, 293 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +button-edge-2 + rotate: false + xy: 451, 343 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +button-edge-3 + rotate: false + xy: 501, 393 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +button-edge-4 + rotate: false + xy: 551, 443 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +button-over + rotate: false + xy: 601, 493 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +button-red + rotate: false + xy: 651, 543 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +button-right + rotate: false + xy: 801, 693 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +button-right-down + rotate: false + xy: 701, 593 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +button-right-over + rotate: false + xy: 751, 643 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +button-select + rotate: false + xy: 417, 5 + size: 24, 24 + split: 4, 4, 4, 4 + orig: 24, 24 + offset: 0, 0 + index: -1 +char-icon-large + rotate: false + xy: 287, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +char-icon-medium + rotate: false + xy: 1212, 888 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +char-icon-small + rotate: false + xy: 448, 57 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +check-disabled + rotate: false + xy: 1246, 888 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +check-off + rotate: false + xy: 1280, 888 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +check-on + rotate: false + xy: 1314, 888 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +check-on-disabled + rotate: false + xy: 1348, 888 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +check-on-over + rotate: false + xy: 1382, 888 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +check-over + rotate: false + xy: 1416, 888 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +clear + rotate: false + xy: 389, 260 + size: 10, 10 + orig: 10, 10 + offset: 0, 0 + index: -1 +cliffs-icon-large + rotate: false + xy: 1, 678 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +cliffs-icon-medium + rotate: false + xy: 1450, 888 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +cliffs-icon-small + rotate: false + xy: 443, 31 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +coal-centrifuge-icon-large + rotate: false + xy: 337, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +coal-centrifuge-icon-medium + rotate: false + xy: 1484, 888 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +coal-centrifuge-icon-small + rotate: false + xy: 443, 5 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +combustion-generator-icon-large + rotate: false + xy: 1, 628 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +combustion-generator-icon-medium + rotate: false + xy: 1518, 888 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +combustion-generator-icon-small + rotate: false + xy: 474, 59 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +conduit-icon-large + rotate: false + xy: 387, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +conduit-icon-medium + rotate: false + xy: 1552, 888 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conduit-icon-small + rotate: false + xy: 2021, 862 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +container-icon-large + rotate: false + xy: 1, 578 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +container-icon-medium + rotate: false + xy: 1586, 888 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +container-icon-small + rotate: false + xy: 469, 31 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +conveyor-icon-large + rotate: false + xy: 437, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +conveyor-icon-medium + rotate: false + xy: 1620, 888 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +conveyor-icon-small + rotate: false + xy: 469, 5 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +copper-wall-icon-large + rotate: false + xy: 1, 528 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +copper-wall-icon-medium + rotate: false + xy: 1654, 888 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +copper-wall-icon-small + rotate: false + xy: 887, 569 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +copper-wall-large-icon-large + rotate: false + xy: 487, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +copper-wall-large-icon-medium + rotate: false + xy: 1688, 888 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +copper-wall-large-icon-small + rotate: false + xy: 913, 569 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +core-foundation-icon-large + rotate: false + xy: 1, 478 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +core-foundation-icon-medium + rotate: false + xy: 1722, 888 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +core-foundation-icon-small + rotate: false + xy: 939, 569 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +core-nucleus-icon-large + rotate: false + xy: 537, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +core-nucleus-icon-medium + rotate: false + xy: 1756, 888 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +core-nucleus-icon-small + rotate: false + xy: 637, 319 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +core-shard-icon-large + rotate: false + xy: 1, 428 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +core-shard-icon-medium + rotate: false + xy: 1790, 888 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +core-shard-icon-small + rotate: false + xy: 663, 319 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +craters-icon-large + rotate: false + xy: 587, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +craters-icon-medium + rotate: false + xy: 1824, 888 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +craters-icon-small + rotate: false + xy: 689, 319 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +crawler-factory-icon-large + rotate: false + xy: 1, 378 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +crawler-factory-icon-medium + rotate: false + xy: 1858, 888 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +crawler-factory-icon-small + rotate: false + xy: 715, 319 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +cryofluidmixer-icon-large + rotate: false + xy: 637, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +cryofluidmixer-icon-medium + rotate: false + xy: 1892, 888 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +cryofluidmixer-icon-small + rotate: false + xy: 500, 53 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +cultivator-icon-large + rotate: false + xy: 1, 328 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +cultivator-icon-medium + rotate: false + xy: 1926, 888 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +cultivator-icon-small + rotate: false + xy: 495, 27 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +cursor + rotate: false + xy: 51, 922 + size: 4, 4 + orig: 4, 4 + offset: 0, 0 + index: -1 +cyclone-icon-large + rotate: false + xy: 687, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +cyclone-icon-medium + rotate: false + xy: 1960, 888 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +cyclone-icon-small + rotate: false + xy: 495, 1 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +dagger-factory-icon-large + rotate: false + xy: 1, 278 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dagger-factory-icon-medium + rotate: false + xy: 1994, 888 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dagger-factory-icon-small + rotate: false + xy: 526, 53 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +dark-metal-icon-large + rotate: false + xy: 737, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dark-metal-icon-medium + rotate: false + xy: 229, 38 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dark-metal-icon-small + rotate: false + xy: 521, 27 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +dark-panel-1-icon-large + rotate: false + xy: 1, 228 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dark-panel-1-icon-medium + rotate: false + xy: 401, 259 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dark-panel-1-icon-small + rotate: false + xy: 521, 1 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +dark-panel-2-icon-large + rotate: false + xy: 787, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dark-panel-2-icon-medium + rotate: false + xy: 389, 225 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dark-panel-2-icon-small + rotate: false + xy: 552, 53 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +dark-panel-3-icon-large + rotate: false + xy: 1, 178 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dark-panel-3-icon-medium + rotate: false + xy: 451, 309 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dark-panel-3-icon-small + rotate: false + xy: 547, 27 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +dark-panel-4-icon-large + rotate: false + xy: 837, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dark-panel-4-icon-medium + rotate: false + xy: 501, 359 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dark-panel-4-icon-small + rotate: false + xy: 547, 1 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +dark-panel-5-icon-large + rotate: false + xy: 1, 128 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dark-panel-5-icon-medium + rotate: false + xy: 551, 409 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dark-panel-5-icon-small + rotate: false + xy: 578, 53 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +dark-panel-6-icon-large + rotate: false + xy: 887, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dark-panel-6-icon-medium + rotate: false + xy: 601, 459 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dark-panel-6-icon-small + rotate: false + xy: 573, 27 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +darksand-icon-large + rotate: false + xy: 1, 78 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +darksand-icon-medium + rotate: false + xy: 651, 509 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +darksand-icon-small + rotate: false + xy: 573, 1 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +darksand-tainted-water-icon-large + rotate: false + xy: 937, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +darksand-tainted-water-icon-medium + rotate: false + xy: 701, 559 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +darksand-tainted-water-icon-small + rotate: false + xy: 599, 27 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +darksand-water-icon-large + rotate: false + xy: 1, 28 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +darksand-water-icon-medium + rotate: false + xy: 751, 609 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +darksand-water-icon-small + rotate: false + xy: 599, 1 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +dart-mech-pad-icon-large + rotate: false + xy: 987, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dart-mech-pad-icon-medium + rotate: false + xy: 801, 659 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dart-mech-pad-icon-small + rotate: false + xy: 1433, 660 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +deepwater-icon-large + rotate: false + xy: 1037, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +deepwater-icon-medium + rotate: false + xy: 851, 709 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +deepwater-icon-small + rotate: false + xy: 1459, 660 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +delta-mech-pad-icon-large + rotate: false + xy: 1087, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +delta-mech-pad-icon-medium + rotate: false + xy: 901, 759 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +delta-mech-pad-icon-small + rotate: false + xy: 1485, 660 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +differential-generator-icon-large + rotate: false + xy: 1137, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +differential-generator-icon-medium + rotate: false + xy: 951, 809 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +differential-generator-icon-small + rotate: false + xy: 1511, 660 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +discord-banner + rotate: false + xy: 1, 975 + size: 84, 45 + orig: 84, 45 + offset: 0, 0 + index: -1 +distributor-icon-large + rotate: false + xy: 1187, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +distributor-icon-medium + rotate: false + xy: 301, 109 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +distributor-icon-small + rotate: false + xy: 1537, 660 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +door-icon-large + rotate: false + xy: 1237, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +door-icon-medium + rotate: false + xy: 1001, 859 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +door-icon-small + rotate: false + xy: 1563, 660 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +door-large-icon-large + rotate: false + xy: 1287, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +door-large-icon-medium + rotate: false + xy: 51, 9 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +door-large-icon-small + rotate: false + xy: 1589, 660 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +draug-factory-icon-large + rotate: false + xy: 1337, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +draug-factory-icon-medium + rotate: false + xy: 85, 9 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +draug-factory-icon-small + rotate: false + xy: 1615, 660 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +dunerocks-icon-large + rotate: false + xy: 1387, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +dunerocks-icon-medium + rotate: false + xy: 119, 4 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +dunerocks-icon-small + rotate: false + xy: 1641, 660 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +duo-icon-large + rotate: false + xy: 1437, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +duo-icon-medium + rotate: false + xy: 153, 4 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +duo-icon-small + rotate: false + xy: 1667, 660 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +flat-down-base + rotate: false + xy: 901, 793 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +force-projector-icon-large + rotate: false + xy: 1487, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +force-projector-icon-medium + rotate: false + xy: 187, 4 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +force-projector-icon-small + rotate: false + xy: 1693, 660 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +fortress-factory-icon-large + rotate: false + xy: 1537, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +fortress-factory-icon-medium + rotate: false + xy: 221, 4 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +fortress-factory-icon-small + rotate: false + xy: 1719, 660 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +fuse-icon-large + rotate: false + xy: 1587, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +fuse-icon-medium + rotate: false + xy: 423, 225 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +fuse-icon-small + rotate: false + xy: 1745, 660 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ghoul-factory-icon-large + rotate: false + xy: 1637, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ghoul-factory-icon-medium + rotate: false + xy: 435, 259 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ghoul-factory-icon-small + rotate: false + xy: 1771, 660 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +glaive-ship-pad-icon-large + rotate: false + xy: 1687, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +glaive-ship-pad-icon-medium + rotate: false + xy: 457, 225 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +glaive-ship-pad-icon-small + rotate: false + xy: 1797, 660 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +graphite-press-icon-large + rotate: false + xy: 1737, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +graphite-press-icon-medium + rotate: false + xy: 389, 191 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +graphite-press-icon-small + rotate: false + xy: 1823, 660 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +grass-icon-large + rotate: false + xy: 1787, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +grass-icon-medium + rotate: false + xy: 423, 191 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +grass-icon-small + rotate: false + xy: 1849, 660 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +hail-icon-large + rotate: false + xy: 1837, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +hail-icon-medium + rotate: false + xy: 457, 191 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +hail-icon-small + rotate: false + xy: 1875, 660 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +holostone-icon-large + rotate: false + xy: 1887, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +holostone-icon-medium + rotate: false + xy: 351, 146 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +holostone-icon-small + rotate: false + xy: 1901, 660 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +hotrock-icon-large + rotate: false + xy: 1937, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +hotrock-icon-medium + rotate: false + xy: 385, 157 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +hotrock-icon-small + rotate: false + xy: 1927, 660 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ice-icon-large + rotate: false + xy: 1987, 972 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ice-icon-medium + rotate: false + xy: 419, 157 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ice-icon-small + rotate: false + xy: 1953, 660 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ice-snow-icon-large + rotate: false + xy: 87, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ice-snow-icon-medium + rotate: false + xy: 453, 157 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ice-snow-icon-small + rotate: false + xy: 1979, 660 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +icerocks-icon-large + rotate: false + xy: 137, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icerocks-icon-medium + rotate: false + xy: 385, 123 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icerocks-icon-small + rotate: false + xy: 2005, 660 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +icon-about + rotate: false + xy: 187, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-about-med + rotate: false + xy: 619, 409 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-about-small + rotate: false + xy: 419, 123 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-add + rotate: false + xy: 237, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-add-med + rotate: false + xy: 869, 659 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-add-small + rotate: false + xy: 453, 123 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-admin + rotate: false + xy: 287, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-admin-med + rotate: false + xy: 1433, 686 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-admin-small + rotate: false + xy: 337, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-admin-small-med + rotate: false + xy: 651, 409 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-admin-small-small + rotate: false + xy: 255, 4 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-arrow + rotate: false + xy: 387, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-arrow-16 + rotate: false + xy: 387, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-arrow-16-med + rotate: false + xy: 637, 377 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-arrow-med + rotate: false + xy: 637, 377 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-arrow-16-small + rotate: false + xy: 263, 59 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-arrow-small + rotate: false + xy: 263, 59 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-arrow-down + rotate: false + xy: 437, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-arrow-down-med + rotate: false + xy: 901, 659 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-arrow-down-small + rotate: false + xy: 297, 75 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-arrow-left + rotate: false + xy: 487, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-arrow-left-med + rotate: false + xy: 887, 627 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-arrow-left-small + rotate: false + xy: 297, 41 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-arrow-right + rotate: false + xy: 537, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-arrow-right-med + rotate: false + xy: 1465, 686 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-arrow-right-small + rotate: false + xy: 289, 7 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-arrow-up + rotate: false + xy: 587, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-arrow-up-med + rotate: false + xy: 683, 409 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-arrow-up-small + rotate: false + xy: 323, 7 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-back + rotate: false + xy: 637, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-back-med + rotate: false + xy: 637, 345 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-back-small + rotate: false + xy: 535, 359 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-ban + rotate: false + xy: 687, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-ban-med + rotate: false + xy: 669, 377 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-ban-small + rotate: false + xy: 585, 409 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-break + rotate: false + xy: 737, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-break-med + rotate: false + xy: 933, 659 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-break-small + rotate: false + xy: 569, 375 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-cancel + rotate: false + xy: 787, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-cancel-med + rotate: false + xy: 887, 595 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-cancel-small + rotate: false + xy: 569, 341 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-changelog + rotate: false + xy: 837, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-changelog-med + rotate: false + xy: 919, 627 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-changelog-small + rotate: false + xy: 603, 375 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-chat + rotate: false + xy: 887, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-chat-med + rotate: false + xy: 1497, 686 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-chat-small + rotate: false + xy: 603, 341 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-check + rotate: false + xy: 937, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-check-med + rotate: false + xy: 715, 409 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-check-small + rotate: false + xy: 639, 475 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-copy + rotate: false + xy: 987, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-copy-med + rotate: false + xy: 669, 345 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-copy-small + rotate: false + xy: 673, 475 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-crafting + rotate: false + xy: 1037, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-crafting-med + rotate: false + xy: 701, 377 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-crafting-small + rotate: false + xy: 685, 509 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-cursor + rotate: false + xy: 1087, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-cursor-med + rotate: false + xy: 919, 595 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-cursor-small + rotate: false + xy: 635, 441 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-database + rotate: false + xy: 1137, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-database-med + rotate: false + xy: 1529, 686 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-database-small + rotate: false + xy: 669, 441 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-defense + rotate: false + xy: 1187, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-defense-med + rotate: false + xy: 701, 345 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-defense-small + rotate: false + xy: 707, 475 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-dev-builds + rotate: false + xy: 1237, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-dev-builds-med + rotate: false + xy: 1561, 686 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-dev-builds-small + rotate: false + xy: 703, 441 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-diagonal + rotate: false + xy: 1287, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-diagonal-med + rotate: false + xy: 1593, 686 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-diagonal-small + rotate: false + xy: 785, 609 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-discord + rotate: false + xy: 1337, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-discord-med + rotate: false + xy: 1625, 686 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-discord-small + rotate: false + xy: 835, 659 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-distribution + rotate: false + xy: 1387, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-distribution-med + rotate: false + xy: 1657, 686 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-distribution-small + rotate: false + xy: 819, 625 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-donate + rotate: false + xy: 1437, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-donate-med + rotate: false + xy: 1689, 686 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-donate-small + rotate: false + xy: 819, 591 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-dots + rotate: false + xy: 1487, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-dots-med + rotate: false + xy: 1721, 686 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-dots-small + rotate: false + xy: 853, 625 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-editor + rotate: false + xy: 1537, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-editor-med + rotate: false + xy: 1753, 686 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-editor-small + rotate: false + xy: 853, 591 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-effect + rotate: false + xy: 1587, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-effect-med + rotate: false + xy: 1785, 686 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-effect-small + rotate: false + xy: 889, 725 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-elevation + rotate: false + xy: 1637, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-elevation-med + rotate: false + xy: 1817, 686 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-elevation-small + rotate: false + xy: 923, 725 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-eraser + rotate: false + xy: 1687, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-eraser-med + rotate: false + xy: 1849, 686 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-eraser-small + rotate: false + xy: 935, 759 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-exit + rotate: false + xy: 1737, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-exit-med + rotate: false + xy: 1881, 686 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-exit-small + rotate: false + xy: 885, 691 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-file + rotate: false + xy: 1787, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-file-image + rotate: false + xy: 1837, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-file-image-med + rotate: false + xy: 1913, 686 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-file-image-small + rotate: false + xy: 919, 691 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-file-med + rotate: false + xy: 1945, 686 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-file-small + rotate: false + xy: 957, 725 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-file-text + rotate: false + xy: 1887, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-file-text-med + rotate: false + xy: 1977, 686 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-file-text-small + rotate: false + xy: 953, 691 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-fill + rotate: false + xy: 1937, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-fill-med + rotate: false + xy: 2009, 686 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-fill-small + rotate: false + xy: 1035, 859 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-floppy + rotate: false + xy: 1987, 922 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-floppy-16 + rotate: false + xy: 51, 872 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-floppy-16-med + rotate: false + xy: 951, 627 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-floppy-16-small + rotate: false + xy: 1069, 854 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-floppy-med + rotate: false + xy: 951, 595 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-floppy-small + rotate: false + xy: 1103, 854 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-folder + rotate: false + xy: 51, 822 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-folder-med + rotate: false + xy: 733, 377 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-folder-parent + rotate: false + xy: 101, 872 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-folder-parent-med + rotate: false + xy: 733, 345 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-folder-parent-small + rotate: false + xy: 1137, 854 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-folder-small + rotate: false + xy: 1171, 854 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-github + rotate: false + xy: 51, 772 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-github-med + rotate: false + xy: 983, 641 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-github-small + rotate: false + xy: 1205, 854 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-google-play + rotate: false + xy: 101, 822 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-google-play-med + rotate: false + xy: 983, 609 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-google-play-small + rotate: false + xy: 1239, 854 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-grid + rotate: false + xy: 151, 872 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-grid-med + rotate: false + xy: 1015, 641 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-grid-small + rotate: false + xy: 1273, 854 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-home + rotate: false + xy: 51, 722 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-home-med + rotate: false + xy: 1015, 609 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-home-small + rotate: false + xy: 1307, 854 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-host + rotate: false + xy: 101, 772 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-host-med + rotate: false + xy: 983, 577 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-host-small + rotate: false + xy: 1341, 854 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-info + rotate: false + xy: 151, 822 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-info-med + rotate: false + xy: 1015, 577 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-info-small + rotate: false + xy: 1375, 854 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-itch.io + rotate: false + xy: 201, 872 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-itch.io-med + rotate: false + xy: 765, 391 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-itch.io-small + rotate: false + xy: 1409, 854 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-item + rotate: false + xy: 51, 672 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-item-med + rotate: false + xy: 765, 359 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-item-small + rotate: false + xy: 1443, 854 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-line + rotate: false + xy: 101, 722 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-line-med + rotate: false + xy: 765, 327 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-line-small + rotate: false + xy: 1477, 854 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-link + rotate: false + xy: 151, 772 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-link-med + rotate: false + xy: 1047, 641 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-link-small + rotate: false + xy: 1511, 854 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-liquid + rotate: false + xy: 201, 822 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-liquid-consume + rotate: false + xy: 251, 872 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-liquid-consume-med + rotate: false + xy: 1047, 609 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-liquid-consume-small + rotate: false + xy: 1545, 854 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-liquid-med + rotate: false + xy: 1047, 577 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-liquid-small + rotate: false + xy: 1579, 854 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-load + rotate: false + xy: 51, 622 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-load-image + rotate: false + xy: 101, 672 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-load-image-med + rotate: false + xy: 1079, 652 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-load-image-small + rotate: false + xy: 1613, 854 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-load-map + rotate: false + xy: 151, 722 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-load-map-med + rotate: false + xy: 1079, 620 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-load-map-small + rotate: false + xy: 1647, 854 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-load-med + rotate: false + xy: 1111, 652 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-load-small + rotate: false + xy: 1681, 854 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-loading + rotate: false + xy: 201, 772 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-loading-med + rotate: false + xy: 1079, 588 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-loading-small + rotate: false + xy: 1715, 854 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-locked + rotate: false + xy: 251, 822 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-locked-med + rotate: false + xy: 1111, 620 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-locked-small + rotate: false + xy: 1749, 854 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-map + rotate: false + xy: 301, 872 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-map-med + rotate: false + xy: 1143, 652 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-map-small + rotate: false + xy: 1783, 854 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-menu + rotate: false + xy: 51, 572 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-menu-large + rotate: false + xy: 101, 622 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-menu-large-med + rotate: false + xy: 1111, 588 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-menu-large-small + rotate: false + xy: 1817, 854 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-menu-med + rotate: false + xy: 1143, 620 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-menu-small + rotate: false + xy: 1851, 854 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-missing + rotate: false + xy: 151, 672 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-missing-med + rotate: false + xy: 1175, 652 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-missing-small + rotate: false + xy: 1885, 854 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-mode-attack + rotate: false + xy: 201, 722 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-mode-attack-med + rotate: false + xy: 1143, 588 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-mode-attack-small + rotate: false + xy: 1919, 854 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-mode-pvp + rotate: false + xy: 251, 772 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-mode-pvp-med + rotate: false + xy: 1175, 620 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-mode-pvp-small + rotate: false + xy: 1953, 854 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-mode-survival + rotate: false + xy: 301, 822 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-mode-survival-med + rotate: false + xy: 1207, 652 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-mode-survival-small + rotate: false + xy: 1987, 854 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-none + rotate: false + xy: 351, 872 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-none-med + rotate: false + xy: 1175, 588 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-none-small + rotate: false + xy: 487, 157 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-paste + rotate: false + xy: 51, 522 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-paste-med + rotate: false + xy: 1207, 620 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-paste-small + rotate: false + xy: 487, 123 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-pause + rotate: false + xy: 101, 572 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-pause-med + rotate: false + xy: 1239, 652 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-pause-small + rotate: false + xy: 335, 109 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-pencil + rotate: false + xy: 151, 622 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-pencil-med + rotate: false + xy: 1207, 588 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-pencil-small + rotate: false + xy: 331, 75 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-pick + rotate: false + xy: 201, 672 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-pick-med + rotate: false + xy: 1239, 620 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-pick-small + rotate: false + xy: 331, 41 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-play + rotate: false + xy: 251, 722 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-play-2 + rotate: false + xy: 301, 772 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-play-2-med + rotate: false + xy: 1271, 652 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-play-2-small + rotate: false + xy: 357, 7 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-play-custom + rotate: false + xy: 351, 822 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-play-custom-med + rotate: false + xy: 1239, 588 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-play-custom-small + rotate: false + xy: 485, 309 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-play-med + rotate: false + xy: 1271, 620 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-play-small + rotate: false + xy: 469, 275 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-players + rotate: false + xy: 401, 872 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-players-med + rotate: false + xy: 1303, 652 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-players-small + rotate: false + xy: 519, 325 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-power + rotate: false + xy: 51, 472 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-power-med + rotate: false + xy: 1271, 588 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-power-small + rotate: false + xy: 503, 275 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-production + rotate: false + xy: 101, 522 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-production-med + rotate: false + xy: 1303, 620 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-production-small + rotate: false + xy: 491, 241 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-quit + rotate: false + xy: 151, 572 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-quit-med + rotate: false + xy: 1335, 652 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-quit-small + rotate: false + xy: 491, 207 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-redo + rotate: false + xy: 201, 622 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-redo-med + rotate: false + xy: 1303, 588 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-redo-small + rotate: false + xy: 525, 241 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-refresh + rotate: false + xy: 251, 672 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-refresh-med + rotate: false + xy: 1335, 620 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-refresh-small + rotate: false + xy: 525, 207 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-rename + rotate: false + xy: 301, 722 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-rename-med + rotate: false + xy: 1367, 652 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-rename-small + rotate: false + xy: 521, 173 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-resize + rotate: false + xy: 351, 772 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-resize-med + rotate: false + xy: 1335, 588 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-resize-small + rotate: false + xy: 521, 139 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-rotate + rotate: false + xy: 401, 822 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-rotate-arrow + rotate: false + xy: 451, 872 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-rotate-arrow-med + rotate: false + xy: 1367, 620 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-rotate-arrow-small + rotate: false + xy: 521, 105 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-rotate-left + rotate: false + xy: 51, 422 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-rotate-left-med + rotate: false + xy: 1399, 652 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-rotate-left-small + rotate: false + xy: 737, 441 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-rotate-med + rotate: false + xy: 1367, 588 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-rotate-right + rotate: false + xy: 101, 472 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-rotate-right-med + rotate: false + xy: 1399, 620 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-rotate-right-small + rotate: false + xy: 735, 559 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-rotate-small + rotate: false + xy: 719, 525 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-save + rotate: false + xy: 151, 522 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-save-image + rotate: false + xy: 201, 572 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-save-image-med + rotate: false + xy: 1399, 588 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-save-image-small + rotate: false + xy: 769, 575 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-save-map + rotate: false + xy: 251, 622 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-save-map-med + rotate: false + xy: 1079, 556 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-save-map-small + rotate: false + xy: 753, 525 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-save-med + rotate: false + xy: 1111, 556 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-save-small + rotate: false + xy: 741, 491 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-settings + rotate: false + xy: 301, 672 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-settings-med + rotate: false + xy: 1143, 556 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-settings-small + rotate: false + xy: 775, 491 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-spray + rotate: false + xy: 351, 722 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-spray-med + rotate: false + xy: 1175, 556 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-spray-small + rotate: false + xy: 771, 457 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-terrain + rotate: false + xy: 401, 772 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-terrain-med + rotate: false + xy: 1207, 556 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-terrain-small + rotate: false + xy: 771, 423 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-tools + rotate: false + xy: 451, 822 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-tools-med + rotate: false + xy: 1239, 556 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-tools-small + rotate: false + xy: 985, 809 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-trash + rotate: false + xy: 501, 872 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-trash-16 + rotate: false + xy: 51, 372 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-trash-16-med + rotate: false + xy: 1271, 556 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-trash-16-small + rotate: false + xy: 969, 775 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-trash-med + rotate: false + xy: 1303, 556 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-trash-small + rotate: false + xy: 1019, 825 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-tree + rotate: false + xy: 101, 422 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-tree-med + rotate: false + xy: 1335, 556 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-tree-small + rotate: false + xy: 1003, 775 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-trello + rotate: false + xy: 151, 472 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-trello-med + rotate: false + xy: 1367, 556 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-trello-small + rotate: false + xy: 991, 741 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-turret + rotate: false + xy: 201, 522 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-turret-med + rotate: false + xy: 1399, 556 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-turret-small + rotate: false + xy: 991, 707 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-tutorial + rotate: false + xy: 251, 572 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-tutorial-med + rotate: false + xy: 797, 391 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-tutorial-small + rotate: false + xy: 1053, 820 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-undo + rotate: false + xy: 301, 622 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-undo-med + rotate: false + xy: 797, 359 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-undo-small + rotate: false + xy: 1087, 820 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-units + rotate: false + xy: 351, 672 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-units-med + rotate: false + xy: 797, 327 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-units-small + rotate: false + xy: 1121, 820 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-unlocks + rotate: false + xy: 401, 722 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-unlocks-med + rotate: false + xy: 555, 175 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-unlocks-small + rotate: false + xy: 1155, 820 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-upgrade + rotate: false + xy: 451, 772 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-upgrade-med + rotate: false + xy: 555, 143 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-upgrade-small + rotate: false + xy: 1189, 820 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-wiki + rotate: false + xy: 501, 822 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-wiki-med + rotate: false + xy: 555, 111 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-wiki-small + rotate: false + xy: 1223, 820 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +icon-zoom + rotate: false + xy: 551, 872 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +icon-zoom-med + rotate: false + xy: 555, 79 + size: 30, 30 + orig: 30, 30 + offset: 0, 0 + index: -1 +icon-zoom-small + rotate: false + xy: 1257, 820 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ignarock-icon-large + rotate: false + xy: 51, 322 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ignarock-icon-medium + rotate: false + xy: 1291, 820 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ignarock-icon-small + rotate: false + xy: 1431, 634 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +impact-reactor-icon-large + rotate: false + xy: 101, 372 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +impact-reactor-icon-medium + rotate: false + xy: 1325, 820 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +impact-reactor-icon-small + rotate: false + xy: 1431, 608 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +incinerator-icon-large + rotate: false + xy: 151, 422 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +incinerator-icon-medium + rotate: false + xy: 1359, 820 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +incinerator-icon-small + rotate: false + xy: 1457, 634 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +info-banner + rotate: false + xy: 1, 928 + size: 84, 45 + orig: 84, 45 + offset: 0, 0 + index: -1 +inventory + rotate: false + xy: 1431, 566 + size: 24, 40 + split: 10, 10, 10, 14 + orig: 24, 40 + offset: 0, 0 + index: -1 +item-source-icon-large + rotate: false + xy: 201, 472 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +item-source-icon-medium + rotate: false + xy: 1393, 820 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-source-icon-small + rotate: false + xy: 1457, 608 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +item-void-icon-large + rotate: false + xy: 251, 522 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +item-void-icon-medium + rotate: false + xy: 1427, 820 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +item-void-icon-small + rotate: false + xy: 1483, 634 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +javelin-ship-pad-icon-large + rotate: false + xy: 301, 572 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +javelin-ship-pad-icon-medium + rotate: false + xy: 1461, 820 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +javelin-ship-pad-icon-small + rotate: false + xy: 1457, 582 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +junction-icon-large + rotate: false + xy: 351, 622 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +junction-icon-medium + rotate: false + xy: 1495, 820 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +junction-icon-small + rotate: false + xy: 1483, 608 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +kiln-icon-large + rotate: false + xy: 401, 672 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +kiln-icon-medium + rotate: false + xy: 1529, 820 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +kiln-icon-small + rotate: false + xy: 1509, 634 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +lancer-icon-large + rotate: false + xy: 451, 722 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +lancer-icon-medium + rotate: false + xy: 1563, 820 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +lancer-icon-small + rotate: false + xy: 1483, 582 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +laser-drill-icon-large + rotate: false + xy: 501, 772 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +laser-drill-icon-medium + rotate: false + xy: 1597, 820 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +laser-drill-icon-small + rotate: false + xy: 1509, 608 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +launch-pad-icon-large + rotate: false + xy: 551, 822 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +launch-pad-icon-medium + rotate: false + xy: 1631, 820 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +launch-pad-icon-small + rotate: false + xy: 1535, 634 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +launch-pad-large-icon-large + rotate: false + xy: 601, 872 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +launch-pad-large-icon-medium + rotate: false + xy: 1665, 820 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +launch-pad-large-icon-small + rotate: false + xy: 1509, 582 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +liquid-junction-icon-large + rotate: false + xy: 51, 272 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +liquid-junction-icon-medium + rotate: false + xy: 1699, 820 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-junction-icon-small + rotate: false + xy: 1535, 608 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +liquid-router-icon-large + rotate: false + xy: 101, 322 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +liquid-router-icon-medium + rotate: false + xy: 1733, 820 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-router-icon-small + rotate: false + xy: 1561, 634 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +liquid-source-icon-large + rotate: false + xy: 151, 372 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +liquid-source-icon-medium + rotate: false + xy: 1767, 820 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-source-icon-small + rotate: false + xy: 1535, 582 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +liquid-tank-icon-large + rotate: false + xy: 201, 422 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +liquid-tank-icon-medium + rotate: false + xy: 1801, 820 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +liquid-tank-icon-small + rotate: false + xy: 1561, 608 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +magmarock-icon-large + rotate: false + xy: 251, 472 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +magmarock-icon-medium + rotate: false + xy: 1835, 820 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +magmarock-icon-small + rotate: false + xy: 1587, 634 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +mass-driver-icon-large + rotate: false + xy: 301, 522 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +mass-driver-icon-medium + rotate: false + xy: 1869, 820 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +mass-driver-icon-small + rotate: false + xy: 1561, 582 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +mechanical-drill-icon-large + rotate: false + xy: 351, 572 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +mechanical-drill-icon-medium + rotate: false + xy: 1903, 820 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +mechanical-drill-icon-small + rotate: false + xy: 1587, 608 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +mechanical-pump-icon-large + rotate: false + xy: 401, 622 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +mechanical-pump-icon-medium + rotate: false + xy: 1937, 820 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +mechanical-pump-icon-small + rotate: false + xy: 1613, 634 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +meltdown-icon-large + rotate: false + xy: 451, 672 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +meltdown-icon-medium + rotate: false + xy: 1971, 820 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +meltdown-icon-small + rotate: false + xy: 1587, 582 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +melter-icon-large + rotate: false + xy: 501, 722 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +melter-icon-medium + rotate: false + xy: 2005, 820 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +melter-icon-small + rotate: false + xy: 1613, 608 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +mend-projector-icon-large + rotate: false + xy: 551, 772 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +mend-projector-icon-medium + rotate: false + xy: 1025, 741 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +mend-projector-icon-small + rotate: false + xy: 1639, 634 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +mender-icon-large + rotate: false + xy: 601, 822 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +mender-icon-medium + rotate: false + xy: 1025, 707 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +mender-icon-small + rotate: false + xy: 1613, 582 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +metal-floor-2-icon-large + rotate: false + xy: 651, 872 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +metal-floor-2-icon-medium + rotate: false + xy: 987, 673 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-2-icon-small + rotate: false + xy: 1639, 608 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +metal-floor-3-icon-large + rotate: false + xy: 51, 222 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +metal-floor-3-icon-medium + rotate: false + xy: 1021, 673 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-3-icon-small + rotate: false + xy: 1665, 634 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +metal-floor-5-icon-large + rotate: false + xy: 101, 272 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +metal-floor-5-icon-medium + rotate: false + xy: 1037, 786 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-5-icon-small + rotate: false + xy: 1639, 582 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +metal-floor-damaged-icon-large + rotate: false + xy: 151, 322 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +metal-floor-damaged-icon-medium + rotate: false + xy: 1071, 786 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-damaged-icon-small + rotate: false + xy: 1665, 608 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +metal-floor-icon-large + rotate: false + xy: 201, 372 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +metal-floor-icon-medium + rotate: false + xy: 1105, 786 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +metal-floor-icon-small + rotate: false + xy: 1691, 634 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +moss-icon-large + rotate: false + xy: 251, 422 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +moss-icon-medium + rotate: false + xy: 1139, 786 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +moss-icon-small + rotate: false + xy: 1665, 582 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +multi-press-icon-large + rotate: false + xy: 301, 472 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +multi-press-icon-medium + rotate: false + xy: 1173, 786 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +multi-press-icon-small + rotate: false + xy: 1691, 608 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +oil-extractor-icon-large + rotate: false + xy: 351, 522 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +oil-extractor-icon-medium + rotate: false + xy: 1207, 786 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +oil-extractor-icon-small + rotate: false + xy: 1717, 634 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +omega-mech-pad-icon-large + rotate: false + xy: 401, 572 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +omega-mech-pad-icon-medium + rotate: false + xy: 1241, 786 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +omega-mech-pad-icon-small + rotate: false + xy: 1691, 582 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +overdrive-projector-icon-large + rotate: false + xy: 451, 622 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +overdrive-projector-icon-medium + rotate: false + xy: 1275, 786 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +overdrive-projector-icon-small + rotate: false + xy: 1717, 608 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +overflow-gate-icon-large + rotate: false + xy: 501, 672 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +overflow-gate-icon-medium + rotate: false + xy: 1309, 786 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +overflow-gate-icon-small + rotate: false + xy: 1743, 634 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +pane + rotate: false + xy: 1001, 893 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +pane-2 + rotate: false + xy: 951, 843 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +pebbles-icon-large + rotate: false + xy: 551, 722 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +pebbles-icon-medium + rotate: false + xy: 1343, 786 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pebbles-icon-small + rotate: false + xy: 1717, 582 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +phantom-factory-icon-large + rotate: false + xy: 601, 772 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +phantom-factory-icon-medium + rotate: false + xy: 1377, 786 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phantom-factory-icon-small + rotate: false + xy: 1743, 608 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +phase-conduit-icon-large + rotate: false + xy: 651, 822 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +phase-conduit-icon-medium + rotate: false + xy: 1411, 786 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-conduit-icon-small + rotate: false + xy: 1769, 634 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +phase-conveyor-icon-large + rotate: false + xy: 701, 872 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +phase-conveyor-icon-medium + rotate: false + xy: 1445, 786 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-conveyor-icon-small + rotate: false + xy: 1743, 582 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +phase-wall-icon-large + rotate: false + xy: 51, 172 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +phase-wall-icon-medium + rotate: false + xy: 1479, 786 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-wall-icon-small + rotate: false + xy: 1769, 608 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +phase-wall-large-icon-large + rotate: false + xy: 101, 222 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +phase-wall-large-icon-medium + rotate: false + xy: 1513, 786 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-wall-large-icon-small + rotate: false + xy: 1795, 634 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +phase-weaver-icon-large + rotate: false + xy: 151, 272 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +phase-weaver-icon-medium + rotate: false + xy: 1547, 786 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +phase-weaver-icon-small + rotate: false + xy: 1769, 582 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +pine-icon-large + rotate: false + xy: 201, 322 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +pine-icon-medium + rotate: false + xy: 1581, 786 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pine-icon-small + rotate: false + xy: 1795, 608 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +plastanium-compressor-icon-large + rotate: false + xy: 251, 372 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +plastanium-compressor-icon-medium + rotate: false + xy: 1615, 786 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +plastanium-compressor-icon-small + rotate: false + xy: 1821, 634 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +pneumatic-drill-icon-large + rotate: false + xy: 301, 422 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +pneumatic-drill-icon-medium + rotate: false + xy: 1649, 786 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pneumatic-drill-icon-small + rotate: false + xy: 1795, 582 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +power-node-icon-large + rotate: false + xy: 351, 472 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +power-node-icon-medium + rotate: false + xy: 1683, 786 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +power-node-icon-small + rotate: false + xy: 1821, 608 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +power-node-large-icon-large + rotate: false + xy: 401, 522 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +power-node-large-icon-medium + rotate: false + xy: 1717, 786 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +power-node-large-icon-small + rotate: false + xy: 1847, 634 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +power-source-icon-large + rotate: false + xy: 451, 572 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +power-source-icon-medium + rotate: false + xy: 1751, 786 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +power-source-icon-small + rotate: false + xy: 1821, 582 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +power-void-icon-large + rotate: false + xy: 501, 622 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +power-void-icon-medium + rotate: false + xy: 1785, 786 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +power-void-icon-small + rotate: false + xy: 1847, 608 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +pulse-conduit-icon-large + rotate: false + xy: 551, 672 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +pulse-conduit-icon-medium + rotate: false + xy: 1819, 786 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pulse-conduit-icon-small + rotate: false + xy: 1873, 634 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +pulverizer-icon-large + rotate: false + xy: 601, 722 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +pulverizer-icon-medium + rotate: false + xy: 1853, 786 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pulverizer-icon-small + rotate: false + xy: 1847, 582 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +pyratite-mixer-icon-large + rotate: false + xy: 651, 772 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +pyratite-mixer-icon-medium + rotate: false + xy: 1887, 786 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +pyratite-mixer-icon-small + rotate: false + xy: 1873, 608 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +repair-point-icon-large + rotate: false + xy: 701, 822 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +repair-point-icon-medium + rotate: false + xy: 1921, 786 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +repair-point-icon-small + rotate: false + xy: 1899, 634 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +revenant-factory-icon-large + rotate: false + xy: 751, 872 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +revenant-factory-icon-medium + rotate: false + xy: 1955, 786 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +revenant-factory-icon-small + rotate: false + xy: 1873, 582 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +ripple-icon-large + rotate: false + xy: 51, 122 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +ripple-icon-medium + rotate: false + xy: 1989, 786 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +ripple-icon-small + rotate: false + xy: 1899, 608 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +rock-icon-large + rotate: false + xy: 101, 172 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +rock-icon-medium + rotate: false + xy: 1059, 752 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +rock-icon-small + rotate: false + xy: 1925, 634 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +rocks-icon-large + rotate: false + xy: 151, 222 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +rocks-icon-medium + rotate: false + xy: 1059, 718 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +rocks-icon-small + rotate: false + xy: 1899, 582 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +rotary-pump-icon-large + rotate: false + xy: 201, 272 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +rotary-pump-icon-medium + rotate: false + xy: 1093, 752 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +rotary-pump-icon-small + rotate: false + xy: 1925, 608 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +router-icon-large + rotate: false + xy: 251, 322 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +router-icon-medium + rotate: false + xy: 1093, 718 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +router-icon-small + rotate: false + xy: 1951, 634 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +rtg-generator-icon-large + rotate: false + xy: 301, 372 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +rtg-generator-icon-medium + rotate: false + xy: 1127, 752 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +rtg-generator-icon-small + rotate: false + xy: 1925, 582 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +salt-icon-large + rotate: false + xy: 351, 422 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +salt-icon-medium + rotate: false + xy: 1127, 718 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +salt-icon-small + rotate: false + xy: 1951, 608 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +saltrocks-icon-large + rotate: false + xy: 401, 472 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +saltrocks-icon-medium + rotate: false + xy: 1161, 752 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +saltrocks-icon-small + rotate: false + xy: 1977, 634 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +salvo-icon-large + rotate: false + xy: 451, 522 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +salvo-icon-medium + rotate: false + xy: 1161, 718 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +salvo-icon-small + rotate: false + xy: 1951, 582 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +sand-boulder-icon-large + rotate: false + xy: 501, 572 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +sand-boulder-icon-medium + rotate: false + xy: 1195, 752 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sand-boulder-icon-small + rotate: false + xy: 1977, 608 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +sand-icon-large + rotate: false + xy: 551, 622 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +sand-icon-medium + rotate: false + xy: 1195, 718 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sand-icon-small + rotate: false + xy: 2003, 634 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +sand-water-icon-large + rotate: false + xy: 601, 672 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +sand-water-icon-medium + rotate: false + xy: 1229, 752 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sand-water-icon-small + rotate: false + xy: 1977, 582 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +sandrocks-icon-large + rotate: false + xy: 651, 722 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +sandrocks-icon-medium + rotate: false + xy: 1229, 718 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sandrocks-icon-small + rotate: false + xy: 2003, 608 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +scatter-icon-large + rotate: false + xy: 701, 772 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +scatter-icon-medium + rotate: false + xy: 1263, 752 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scatter-icon-small + rotate: false + xy: 2003, 582 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +scorch-icon-large + rotate: false + xy: 751, 822 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +scorch-icon-medium + rotate: false + xy: 1263, 718 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scorch-icon-small + rotate: false + xy: 1457, 556 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +scrap-wall-gigantic-icon-large + rotate: false + xy: 801, 872 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +scrap-wall-gigantic-icon-medium + rotate: false + xy: 1297, 752 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap-wall-gigantic-icon-small + rotate: false + xy: 1483, 556 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +scrap-wall-huge-icon-large + rotate: false + xy: 51, 72 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +scrap-wall-huge-icon-medium + rotate: false + xy: 1297, 718 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap-wall-huge-icon-small + rotate: false + xy: 1509, 556 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +scrap-wall-icon-large + rotate: false + xy: 101, 122 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +scrap-wall-icon-medium + rotate: false + xy: 1331, 752 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap-wall-icon-small + rotate: false + xy: 1535, 556 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +scrap-wall-large-icon-large + rotate: false + xy: 151, 172 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +scrap-wall-large-icon-medium + rotate: false + xy: 1331, 718 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +scrap-wall-large-icon-small + rotate: false + xy: 1561, 556 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +scroll + rotate: false + xy: 1613, 545 + size: 24, 35 + split: 10, 10, 6, 5 + orig: 24, 35 + offset: 0, 0 + index: -1 +scroll-horizontal + rotate: false + xy: 1039, 896 + size: 35, 24 + split: 6, 5, 10, 10 + orig: 35, 24 + offset: 0, 0 + index: -1 +scroll-knob-horizontal-black + rotate: false + xy: 1, 2 + size: 40, 24 + split: 11, 10, 10, 10 + orig: 40, 24 + offset: 0, 0 + index: -1 +scroll-knob-vertical-black + rotate: false + xy: 1587, 540 + size: 24, 40 + split: 10, 10, 6, 10 + orig: 24, 40 + offset: 0, 0 + index: -1 +selection + rotate: false + xy: 1049, 893 + size: 1, 1 + orig: 1, 1 + offset: 0, 0 + index: -1 +separator-icon-large + rotate: false + xy: 201, 222 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +separator-icon-medium + rotate: false + xy: 1365, 752 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +separator-icon-small + rotate: false + xy: 1639, 556 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +shale-boulder-icon-large + rotate: false + xy: 251, 272 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +shale-boulder-icon-medium + rotate: false + xy: 1365, 718 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +shale-boulder-icon-small + rotate: false + xy: 1665, 556 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +shale-icon-large + rotate: false + xy: 301, 322 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +shale-icon-medium + rotate: false + xy: 1399, 752 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +shale-icon-small + rotate: false + xy: 1691, 556 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +shalerocks-icon-large + rotate: false + xy: 351, 372 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +shalerocks-icon-medium + rotate: false + xy: 1399, 718 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +shalerocks-icon-small + rotate: false + xy: 1717, 556 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +shock-mine-icon-large + rotate: false + xy: 401, 422 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +shock-mine-icon-medium + rotate: false + xy: 1433, 752 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +shock-mine-icon-small + rotate: false + xy: 1743, 556 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +shrubs-icon-large + rotate: false + xy: 451, 472 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +shrubs-icon-medium + rotate: false + xy: 1433, 718 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +shrubs-icon-small + rotate: false + xy: 1769, 556 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +silicon-smelter-icon-large + rotate: false + xy: 501, 522 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +silicon-smelter-icon-medium + rotate: false + xy: 1467, 752 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +silicon-smelter-icon-small + rotate: false + xy: 1795, 556 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +slider + rotate: false + xy: 43, 18 + size: 1, 8 + orig: 1, 8 + offset: 0, 0 + index: -1 +slider-knob + rotate: false + xy: 365, 69 + size: 29, 38 + orig: 29, 38 + offset: 0, 0 + index: -1 +slider-knob-down + rotate: false + xy: 396, 83 + size: 29, 38 + orig: 29, 38 + offset: 0, 0 + index: -1 +slider-knob-over + rotate: false + xy: 427, 83 + size: 29, 38 + orig: 29, 38 + offset: 0, 0 + index: -1 +slider-vertical + rotate: false + xy: 1039, 893 + size: 8, 1 + orig: 8, 1 + offset: 0, 0 + index: -1 +snow-icon-large + rotate: false + xy: 551, 572 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +snow-icon-medium + rotate: false + xy: 1467, 718 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +snow-icon-small + rotate: false + xy: 1821, 556 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +snow-pine-icon-large + rotate: false + xy: 601, 622 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +snow-pine-icon-medium + rotate: false + xy: 1501, 752 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +snow-pine-icon-small + rotate: false + xy: 1847, 556 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +snowrock-icon-large + rotate: false + xy: 651, 672 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +snowrock-icon-medium + rotate: false + xy: 1501, 718 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +snowrock-icon-small + rotate: false + xy: 1873, 556 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +snowrocks-icon-large + rotate: false + xy: 701, 722 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +snowrocks-icon-medium + rotate: false + xy: 1535, 752 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +snowrocks-icon-small + rotate: false + xy: 1899, 556 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +solar-panel-icon-large + rotate: false + xy: 751, 772 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +solar-panel-icon-medium + rotate: false + xy: 1535, 718 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +solar-panel-icon-small + rotate: false + xy: 1925, 556 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +solar-panel-large-icon-large + rotate: false + xy: 801, 822 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +solar-panel-large-icon-medium + rotate: false + xy: 1569, 752 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +solar-panel-large-icon-small + rotate: false + xy: 1951, 556 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +sorter-icon-large + rotate: false + xy: 851, 872 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +sorter-icon-medium + rotate: false + xy: 1569, 718 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sorter-icon-small + rotate: false + xy: 1977, 556 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +spawn-icon-large + rotate: false + xy: 101, 72 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +spawn-icon-medium + rotate: false + xy: 1603, 752 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spawn-icon-small + rotate: false + xy: 2003, 556 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +spectre-icon-large + rotate: false + xy: 151, 122 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +spectre-icon-medium + rotate: false + xy: 1603, 718 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spectre-icon-small + rotate: false + xy: 1431, 540 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +spirit-factory-icon-large + rotate: false + xy: 201, 172 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +spirit-factory-icon-medium + rotate: false + xy: 1637, 752 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spirit-factory-icon-small + rotate: false + xy: 1457, 530 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +spore-cluster-icon-large + rotate: false + xy: 251, 222 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +spore-cluster-icon-medium + rotate: false + xy: 1637, 718 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spore-cluster-icon-small + rotate: false + xy: 1483, 530 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +spore-moss-icon-large + rotate: false + xy: 301, 272 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +spore-moss-icon-medium + rotate: false + xy: 1671, 752 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spore-moss-icon-small + rotate: false + xy: 1509, 530 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +spore-pine-icon-large + rotate: false + xy: 351, 322 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +spore-pine-icon-medium + rotate: false + xy: 1671, 718 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spore-pine-icon-small + rotate: false + xy: 1535, 530 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +spore-press-icon-large + rotate: false + xy: 401, 372 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +spore-press-icon-medium + rotate: false + xy: 1705, 752 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +spore-press-icon-small + rotate: false + xy: 1561, 530 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +sporerocks-icon-large + rotate: false + xy: 451, 422 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +sporerocks-icon-medium + rotate: false + xy: 1705, 718 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +sporerocks-icon-small + rotate: false + xy: 1639, 530 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +stone-icon-large + rotate: false + xy: 501, 472 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +stone-icon-medium + rotate: false + xy: 1739, 752 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +stone-icon-small + rotate: false + xy: 1665, 530 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +surge-tower-icon-large + rotate: false + xy: 551, 522 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +surge-tower-icon-medium + rotate: false + xy: 1739, 718 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +surge-tower-icon-small + rotate: false + xy: 1691, 530 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +surge-wall-icon-large + rotate: false + xy: 601, 572 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +surge-wall-icon-medium + rotate: false + xy: 1773, 752 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +surge-wall-icon-small + rotate: false + xy: 1717, 530 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +surge-wall-large-icon-large + rotate: false + xy: 651, 622 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +surge-wall-large-icon-medium + rotate: false + xy: 1773, 718 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +surge-wall-large-icon-small + rotate: false + xy: 1743, 530 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +swarmer-icon-large + rotate: false + xy: 701, 672 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +swarmer-icon-medium + rotate: false + xy: 1807, 752 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +swarmer-icon-small + rotate: false + xy: 1769, 530 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +tainted-water-icon-large + rotate: false + xy: 751, 722 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +tainted-water-icon-medium + rotate: false + xy: 1807, 718 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +tainted-water-icon-small + rotate: false + xy: 1795, 530 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +tar-icon-large + rotate: false + xy: 801, 772 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +tar-icon-medium + rotate: false + xy: 1841, 752 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +tar-icon-small + rotate: false + xy: 1821, 530 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +tau-mech-pad-icon-large + rotate: false + xy: 851, 822 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +tau-mech-pad-icon-medium + rotate: false + xy: 1841, 718 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +tau-mech-pad-icon-small + rotate: false + xy: 1847, 530 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +tendrils-icon-large + rotate: false + xy: 901, 872 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +tendrils-icon-medium + rotate: false + xy: 1875, 752 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +tendrils-icon-small + rotate: false + xy: 1873, 530 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +thermal-generator-icon-large + rotate: false + xy: 151, 72 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +thermal-generator-icon-medium + rotate: false + xy: 1875, 718 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +thermal-generator-icon-small + rotate: false + xy: 1899, 530 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +thermal-pump-icon-large + rotate: false + xy: 201, 122 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +thermal-pump-icon-medium + rotate: false + xy: 1909, 752 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +thermal-pump-icon-small + rotate: false + xy: 1925, 530 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +thorium-reactor-icon-large + rotate: false + xy: 251, 172 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +thorium-reactor-icon-medium + rotate: false + xy: 1909, 718 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +thorium-reactor-icon-small + rotate: false + xy: 1951, 530 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +thorium-wall-icon-large + rotate: false + xy: 301, 222 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +thorium-wall-icon-medium + rotate: false + xy: 1943, 752 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +thorium-wall-icon-small + rotate: false + xy: 1977, 530 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +thorium-wall-large-icon-large + rotate: false + xy: 351, 272 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +thorium-wall-large-icon-medium + rotate: false + xy: 1943, 718 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +thorium-wall-large-icon-small + rotate: false + xy: 2003, 530 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +thruster-icon-large + rotate: false + xy: 401, 322 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +thruster-icon-medium + rotate: false + xy: 1977, 752 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +thruster-icon-small + rotate: false + xy: 1613, 519 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +titan-factory-icon-large + rotate: false + xy: 451, 372 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +titan-factory-icon-medium + rotate: false + xy: 1977, 718 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titan-factory-icon-small + rotate: false + xy: 1587, 514 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +titanium-conveyor-icon-large + rotate: false + xy: 501, 422 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +titanium-conveyor-icon-medium + rotate: false + xy: 2011, 752 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium-conveyor-icon-small + rotate: false + xy: 1639, 504 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +titanium-wall-icon-large + rotate: false + xy: 551, 472 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +titanium-wall-icon-medium + rotate: false + xy: 2011, 718 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium-wall-icon-small + rotate: false + xy: 1665, 504 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +titanium-wall-large-icon-large + rotate: false + xy: 601, 522 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +titanium-wall-large-icon-medium + rotate: false + xy: 1059, 684 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +titanium-wall-large-icon-small + rotate: false + xy: 1691, 504 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +trident-ship-pad-icon-large + rotate: false + xy: 651, 572 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +trident-ship-pad-icon-medium + rotate: false + xy: 1093, 684 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +trident-ship-pad-icon-small + rotate: false + xy: 1717, 504 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +turbine-generator-icon-large + rotate: false + xy: 701, 622 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +turbine-generator-icon-medium + rotate: false + xy: 1127, 684 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +turbine-generator-icon-small + rotate: false + xy: 1743, 504 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +underline + rotate: false + xy: 351, 214 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +underline-2 + rotate: false + xy: 251, 93 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +underline-disabled + rotate: false + xy: 301, 143 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +underline-red + rotate: false + xy: 89, 43 + size: 36, 27 + split: 12, 12, 12, 12 + orig: 36, 27 + offset: 0, 0 + index: -1 +unloader-icon-large + rotate: false + xy: 751, 672 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +unloader-icon-medium + rotate: false + xy: 1161, 684 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +unloader-icon-small + rotate: false + xy: 1769, 504 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +vault-icon-large + rotate: false + xy: 801, 722 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +vault-icon-medium + rotate: false + xy: 1195, 684 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +vault-icon-small + rotate: false + xy: 1795, 504 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +water-extractor-icon-large + rotate: false + xy: 851, 772 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +water-extractor-icon-medium + rotate: false + xy: 1229, 684 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +water-extractor-icon-small + rotate: false + xy: 1821, 504 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +water-icon-large + rotate: false + xy: 901, 822 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +water-icon-medium + rotate: false + xy: 1263, 684 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +water-icon-small + rotate: false + xy: 1847, 504 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +wave-icon-large + rotate: false + xy: 951, 872 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +wave-icon-medium + rotate: false + xy: 1297, 684 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +wave-icon-small + rotate: false + xy: 1873, 504 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +white-tree-dead-icon-large + rotate: false + xy: 201, 72 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +white-tree-dead-icon-medium + rotate: false + xy: 1331, 684 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +white-tree-dead-icon-small + rotate: false + xy: 1899, 504 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +white-tree-icon-large + rotate: false + xy: 251, 122 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +white-tree-icon-medium + rotate: false + xy: 1365, 684 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +white-tree-icon-small + rotate: false + xy: 1925, 504 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 +whiteui + rotate: false + xy: 119, 38 + size: 3, 3 + orig: 3, 3 + offset: 0, 0 + index: -1 +window-empty + rotate: false + xy: 805, 428 + size: 27, 61 + split: 8, 8, 44, 11 + orig: 27, 61 + offset: 0, 0 + index: -1 +wraith-factory-icon-large + rotate: false + xy: 301, 172 + size: 48, 48 + orig: 48, 48 + offset: 0, 0 + index: -1 +wraith-factory-icon-medium + rotate: false + xy: 1399, 684 + size: 32, 32 + orig: 32, 32 + offset: 0, 0 + index: -1 +wraith-factory-icon-small + rotate: false + xy: 1951, 504 + size: 24, 24 + orig: 24, 24 + offset: 0, 0 + index: -1 diff --git a/core/assets/sprites/sprites.png b/core/assets/sprites/sprites.png index df518b8fdc..2fd70aacfd 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 index 79857b3b36..a91b795504 100644 Binary files a/core/assets/sprites/sprites2.png and b/core/assets/sprites/sprites2.png differ diff --git a/core/assets/sprites/sprites3.png b/core/assets/sprites/sprites3.png index f882d80099..71e777e7de 100644 Binary files a/core/assets/sprites/sprites3.png and b/core/assets/sprites/sprites3.png differ diff --git a/core/assets/sprites/sprites4.png b/core/assets/sprites/sprites4.png new file mode 100644 index 0000000000..8840e3ee12 Binary files /dev/null and b/core/assets/sprites/sprites4.png differ diff --git a/core/assets/sprites/sprites_fallback.atlas b/core/assets/sprites/sprites_fallback.atlas deleted file mode 100644 index bec8bcb7c3..0000000000 --- a/core/assets/sprites/sprites_fallback.atlas +++ /dev/null @@ -1,11728 +0,0 @@ - -sprites_fallback.png -size: 1024,1024 -format: RGBA8888 -filter: Nearest,Nearest -repeat: none -blast-drill - rotate: false - xy: 850, 269 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -blast-drill-rim - rotate: false - xy: 219, 29 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -blast-drill-rotator - rotate: false - xy: 349, 29 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -core-nucleus - rotate: false - xy: 526, 403 - size: 160, 160 - orig: 160, 160 - offset: 0, 0 - index: -1 -core-nucleus-icon-editor - rotate: false - xy: 526, 403 - size: 160, 160 - orig: 160, 160 - offset: 0, 0 - index: -1 -blast-drill-icon-editor - rotate: false - xy: 842, 139 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -white-tree-dead-icon-editor - rotate: false - xy: 1, 243 - size: 320, 320 - orig: 320, 320 - offset: 0, 0 - index: -1 -white-tree-icon-editor - rotate: false - xy: 323, 565 - size: 320, 320 - orig: 320, 320 - offset: 0, 0 - index: -1 -circle-shadow - rotate: false - xy: 323, 159 - size: 201, 201 - orig: 201, 201 - offset: 0, 0 - index: -1 -blast-drill-icon-full - rotate: false - xy: 842, 9 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -cracks-5-0 - rotate: false - xy: 526, 241 - size: 160, 160 - orig: 160, 160 - offset: 0, 0 - index: -1 -cracks-5-1 - rotate: false - xy: 526, 79 - size: 160, 160 - orig: 160, 160 - offset: 0, 0 - index: -1 -cracks-5-2 - rotate: false - xy: 645, 813 - size: 160, 160 - orig: 160, 160 - offset: 0, 0 - index: -1 -cracks-5-3 - rotate: false - xy: 645, 651 - size: 160, 160 - orig: 160, 160 - offset: 0, 0 - index: -1 -cracks-5-4 - rotate: false - xy: 807, 813 - size: 160, 160 - orig: 160, 160 - offset: 0, 0 - index: -1 -cracks-5-5 - rotate: false - xy: 807, 651 - size: 160, 160 - orig: 160, 160 - offset: 0, 0 - index: -1 -cracks-5-6 - rotate: false - xy: 688, 489 - size: 160, 160 - orig: 160, 160 - offset: 0, 0 - index: -1 -cracks-5-7 - rotate: false - xy: 688, 327 - size: 160, 160 - orig: 160, 160 - offset: 0, 0 - index: -1 -unit-icon-eradicator - rotate: false - xy: 850, 399 - size: 152, 124 - orig: 152, 124 - offset: 0, 0 - index: -1 -circle - rotate: false - xy: 323, 362 - size: 201, 201 - orig: 201, 201 - offset: 0, 0 - index: -1 -logotext - rotate: false - xy: 1, 887 - size: 579, 86 - orig: 579, 86 - offset: 0, 0 - index: -1 -eradicator - rotate: false - xy: 688, 201 - size: 152, 124 - orig: 152, 124 - offset: 0, 0 - index: -1 -eradicator-base - rotate: false - xy: 688, 75 - size: 152, 124 - orig: 152, 124 - offset: 0, 0 - index: -1 -eradicator-leg - rotate: false - xy: 850, 525 - size: 152, 124 - orig: 152, 124 - offset: 0, 0 - index: -1 -lich - rotate: false - xy: 1, 1 - size: 216, 240 - orig: 216, 240 - offset: 0, 0 - index: -1 -reaper - rotate: false - xy: 1, 565 - size: 320, 320 - orig: 320, 320 - offset: 0, 0 - index: -1 - -sprites_fallback2.png -size: 1024,1024 -format: RGBA8888 -filter: Nearest,Nearest -repeat: none -force-projector - rotate: false - xy: 619, 211 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -force-projector-icon-editor - rotate: false - xy: 619, 211 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -force-projector-top - rotate: false - xy: 703, 113 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -blast-drill-top - rotate: false - xy: 1, 895 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -rubble-4-0 - rotate: false - xy: 391, 505 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -rubble-4-1 - rotate: false - xy: 391, 505 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -battery-large - rotate: false - xy: 311, 17 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -battery-large-icon-editor - rotate: false - xy: 311, 17 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -differential-generator - rotate: false - xy: 619, 407 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -differential-generator-icon-editor - rotate: false - xy: 619, 407 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -differential-generator-top - rotate: false - xy: 619, 309 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -impact-reactor - rotate: false - xy: 131, 635 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -impact-reactor-bottom - rotate: false - xy: 131, 505 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -impact-reactor-light - rotate: false - xy: 131, 115 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -impact-reactor-plasma-0 - rotate: false - xy: 261, 765 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -impact-reactor-plasma-1 - rotate: false - xy: 391, 765 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -impact-reactor-plasma-2 - rotate: false - xy: 521, 765 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -impact-reactor-plasma-3 - rotate: false - xy: 651, 765 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -impact-reactor-top - rotate: false - xy: 781, 765 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -alloy-smelter - rotate: false - xy: 115, 17 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -alloy-smelter-icon-editor - rotate: false - xy: 115, 17 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -alloy-smelter-top - rotate: false - xy: 213, 17 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -core-foundation - rotate: false - xy: 1, 245 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -core-foundation-icon-editor - rotate: false - xy: 1, 245 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -core-shard - rotate: false - xy: 507, 17 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -core-shard-icon-editor - rotate: false - xy: 507, 17 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -launch-pad-large - rotate: false - xy: 261, 635 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -launch-pad-large-icon-editor - rotate: false - xy: 261, 635 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -block-3 - rotate: false - xy: 409, 17 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -block-4 - rotate: false - xy: 1, 765 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -meltdown-heat - rotate: false - xy: 261, 375 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -fortress-factory - rotate: false - xy: 717, 213 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -fortress-factory-top - rotate: false - xy: 801, 17 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -ghoul-factory-top - rotate: false - xy: 801, 17 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -titan-factory-top - rotate: false - xy: 801, 17 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -ghoul-factory - rotate: false - xy: 899, 45 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -revenant-factory - rotate: false - xy: 391, 635 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -revenant-factory-top - rotate: false - xy: 781, 635 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -scrap-wall-gigantic - rotate: false - xy: 391, 375 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -scrap-wall-gigantic-icon-editor - rotate: false - xy: 391, 375 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -thruster - rotate: false - xy: 651, 505 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -thruster-icon-editor - rotate: false - xy: 651, 505 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -cyclone-icon-editor - rotate: false - xy: 605, 113 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -fortress-factory-icon-editor - rotate: false - xy: 703, 15 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -fuse-icon-editor - rotate: false - xy: 815, 241 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -ghoul-factory-icon-editor - rotate: false - xy: 913, 339 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -impact-reactor-icon-editor - rotate: false - xy: 131, 375 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -meltdown-icon-editor - rotate: false - xy: 261, 245 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -revenant-factory-icon-editor - rotate: false - xy: 521, 635 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -spectre-icon-editor - rotate: false - xy: 391, 115 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -cracks-3-0 - rotate: false - xy: 911, 927 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -cracks-3-1 - rotate: false - xy: 911, 829 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -cracks-3-2 - rotate: false - xy: 911, 731 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -cracks-3-3 - rotate: false - xy: 911, 633 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -cracks-3-4 - rotate: false - xy: 911, 535 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -cracks-3-5 - rotate: false - xy: 911, 437 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -cracks-3-6 - rotate: false - xy: 521, 407 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -cracks-3-7 - rotate: false - xy: 521, 309 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -cracks-4-0 - rotate: false - xy: 1, 115 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -cracks-4-1 - rotate: false - xy: 131, 895 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -cracks-4-2 - rotate: false - xy: 261, 895 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -cracks-4-3 - rotate: false - xy: 391, 895 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -cracks-4-4 - rotate: false - xy: 521, 895 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -cracks-4-5 - rotate: false - xy: 651, 895 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -cracks-4-6 - rotate: false - xy: 781, 895 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -cracks-4-7 - rotate: false - xy: 131, 765 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -cyclone - rotate: false - xy: 521, 211 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -cyclone-icon-full - rotate: false - xy: 605, 15 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -fortress-factory-icon-full - rotate: false - xy: 801, 115 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -fuse - rotate: false - xy: 815, 339 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -fuse-icon-full - rotate: false - xy: 899, 143 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -ghoul-factory-icon-full - rotate: false - xy: 913, 241 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -impact-reactor-icon-full - rotate: false - xy: 131, 245 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -meltdown - rotate: false - xy: 261, 505 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -meltdown-icon-full - rotate: false - xy: 261, 115 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -revenant-factory-icon-full - rotate: false - xy: 651, 635 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -spectre - rotate: false - xy: 391, 245 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -spectre-icon-full - rotate: false - xy: 521, 505 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -unit-icon-chaos-array - rotate: false - xy: 781, 505 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -chaos-array - rotate: false - xy: 1, 635 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -chaos-array-base - rotate: false - xy: 1, 505 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -chaos-array-leg - rotate: false - xy: 1, 375 - size: 128, 128 - orig: 128, 128 - offset: 0, 0 - index: -1 -revenant - rotate: false - xy: 1, 1 - size: 112, 112 - orig: 112, 112 - offset: 0, 0 - index: -1 -eradication-equip - rotate: false - xy: 717, 311 - size: 96, 192 - orig: 96, 192 - offset: 0, 0 - index: -1 - -sprites_fallback3.png -size: 1024,1024 -format: RGBA8888 -filter: Nearest,Nearest -repeat: none -mend-projector - rotate: false - xy: 463, 289 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -mend-projector-icon-editor - rotate: false - xy: 463, 289 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -mend-projector-top - rotate: false - xy: 529, 289 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -overdrive-projector - rotate: false - xy: 661, 289 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -overdrive-projector-icon-editor - rotate: false - xy: 661, 289 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -overdrive-projector-top - rotate: false - xy: 1, 265 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -distributor - rotate: false - xy: 265, 382 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -distributor-icon-editor - rotate: false - xy: 265, 382 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -mass-driver-base - rotate: false - xy: 393, 823 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -laser-drill - rotate: false - xy: 99, 921 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -laser-drill-rim - rotate: false - xy: 393, 921 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -laser-drill-rotator - rotate: false - xy: 491, 921 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -laser-drill-top - rotate: false - xy: 589, 921 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -mechanical-drill - rotate: false - xy: 727, 297 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -mechanical-drill-rotator - rotate: false - xy: 925, 297 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -mechanical-drill-top - rotate: false - xy: 397, 289 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -oil-extractor - rotate: false - xy: 785, 823 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -oil-extractor-liquid - rotate: false - xy: 99, 725 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -oil-extractor-rotator - rotate: false - xy: 197, 725 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -oil-extractor-top - rotate: false - xy: 295, 725 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -pneumatic-drill - rotate: false - xy: 529, 223 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -pneumatic-drill-rotator - rotate: false - xy: 1, 199 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -pneumatic-drill-top - rotate: false - xy: 67, 199 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -place-arrow - rotate: false - xy: 491, 725 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -rubble-1-0 - rotate: false - xy: 793, 165 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -rubble-1-1 - rotate: false - xy: 859, 165 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -rubble-2-0 - rotate: false - xy: 925, 165 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -rubble-2-1 - rotate: false - xy: 397, 157 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -rubble-3-0 - rotate: false - xy: 1, 627 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -rubble-3-1 - rotate: false - xy: 1, 627 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -liquid-tank-bottom - rotate: false - xy: 785, 921 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -liquid-tank-liquid - rotate: false - xy: 99, 823 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -liquid-tank-top - rotate: false - xy: 197, 823 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -rotary-pump - rotate: false - xy: 331, 184 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -rotary-pump-icon-editor - rotate: false - xy: 331, 184 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -thermal-pump - rotate: false - xy: 491, 627 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -thermal-pump-icon-editor - rotate: false - xy: 491, 627 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -dart-mech-pad - rotate: false - xy: 133, 397 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -dart-mech-pad-icon-editor - rotate: false - xy: 133, 397 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -delta-mech-pad - rotate: false - xy: 199, 397 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -delta-mech-pad-icon-editor - rotate: false - xy: 199, 397 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -glaive-ship-pad - rotate: false - xy: 1, 921 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -glaive-ship-pad-icon-editor - rotate: false - xy: 1, 921 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -javelin-ship-pad - rotate: false - xy: 661, 355 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -javelin-ship-pad-icon-editor - rotate: false - xy: 661, 355 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -omega-mech-pad - rotate: false - xy: 393, 725 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -omega-mech-pad-icon-editor - rotate: false - xy: 393, 725 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -tau-mech-pad - rotate: false - xy: 661, 25 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -tau-mech-pad-icon-editor - rotate: false - xy: 661, 25 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -power-node-large - rotate: false - xy: 133, 199 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -rtg-generator - rotate: false - xy: 727, 165 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -rtg-generator-icon-editor - rotate: false - xy: 727, 165 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -solar-panel-large - rotate: false - xy: 393, 627 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -solar-panel-large-icon-editor - rotate: false - xy: 393, 627 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -surge-tower - rotate: false - xy: 925, 33 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -surge-tower-icon-editor - rotate: false - xy: 925, 33 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -thermal-generator - rotate: false - xy: 1, 1 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -thermal-generator-icon-editor - rotate: false - xy: 1, 1 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -thorium-reactor - rotate: false - xy: 589, 627 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -thorium-reactor-icon-editor - rotate: false - xy: 589, 627 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -thorium-reactor-center - rotate: false - xy: 687, 627 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -thorium-reactor-lights - rotate: false - xy: 785, 627 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -blast-mixer - rotate: false - xy: 763, 561 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -blast-mixer-icon-editor - rotate: false - xy: 763, 561 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -coal-centrifuge - rotate: false - xy: 895, 561 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -coal-centrifuge-icon-editor - rotate: false - xy: 895, 561 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -cryofluidmixer-bottom - rotate: false - xy: 265, 448 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -cryofluidmixer-liquid - rotate: false - xy: 823, 429 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -cryofluidmixer-top - rotate: false - xy: 889, 429 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -cultivator - rotate: false - xy: 955, 429 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -cultivator-middle - rotate: false - xy: 529, 421 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -cultivator-top - rotate: false - xy: 595, 421 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -graphite-press - rotate: false - xy: 595, 355 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -graphite-press-icon-editor - rotate: false - xy: 595, 355 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -kiln - rotate: false - xy: 1, 331 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -kiln-icon-editor - rotate: false - xy: 1, 331 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -kiln-top - rotate: false - xy: 67, 331 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -silicon-smelter-top - rotate: false - xy: 67, 331 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -multi-press - rotate: false - xy: 687, 823 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -multi-press-icon-editor - rotate: false - xy: 687, 823 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -phase-weaver - rotate: false - xy: 331, 250 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -phase-weaver-bottom - rotate: false - xy: 727, 231 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -phase-weaver-weave - rotate: false - xy: 925, 231 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -plastanium-compressor - rotate: false - xy: 397, 223 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -plastanium-compressor-icon-editor - rotate: false - xy: 397, 223 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -plastanium-compressor-top - rotate: false - xy: 463, 223 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -pyratite-mixer - rotate: false - xy: 265, 184 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -pyratite-mixer-icon-editor - rotate: false - xy: 265, 184 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -separator - rotate: false - xy: 397, 91 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -separator-icon-editor - rotate: false - xy: 397, 91 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -separator-liquid - rotate: false - xy: 463, 91 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -silicon-smelter - rotate: false - xy: 529, 91 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -silicon-smelter-icon-editor - rotate: false - xy: 529, 91 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -spore-press - rotate: false - xy: 67, 67 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -spore-press-frame0 - rotate: false - xy: 133, 67 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -spore-press-frame1 - rotate: false - xy: 199, 67 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -spore-press-frame2 - rotate: false - xy: 265, 52 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -spore-press-liquid - rotate: false - xy: 793, 33 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -spore-press-top - rotate: false - xy: 859, 33 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -container - rotate: false - xy: 295, 514 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -container-icon-editor - rotate: false - xy: 295, 514 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -launch-pad - rotate: false - xy: 687, 921 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -launch-pad-icon-editor - rotate: false - xy: 687, 921 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -vault - rotate: false - xy: 197, 529 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -vault-icon-editor - rotate: false - xy: 197, 529 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -block-2 - rotate: false - xy: 829, 561 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -lancer-heat - rotate: false - xy: 199, 331 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -ripple-heat - rotate: false - xy: 687, 725 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -salvo-heat - rotate: false - xy: 529, 157 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -salvo-panel-left - rotate: false - xy: 1, 133 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -salvo-panel-right - rotate: false - xy: 67, 133 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -crawler-factory - rotate: false - xy: 1, 463 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -dagger-factory - rotate: false - xy: 1, 463 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -phantom-factory - rotate: false - xy: 1, 463 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -spirit-factory - rotate: false - xy: 1, 463 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -wraith-factory - rotate: false - xy: 1, 463 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -crawler-factory-top - rotate: false - xy: 199, 463 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -dagger-factory-top - rotate: false - xy: 67, 397 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -phantom-factory-top - rotate: false - xy: 199, 265 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -spirit-factory-top - rotate: false - xy: 1, 67 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -titan-factory - rotate: false - xy: 883, 627 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -copper-wall-large - rotate: false - xy: 361, 514 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -copper-wall-large-icon-editor - rotate: false - xy: 361, 514 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -door-large - rotate: false - xy: 331, 382 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -door-large-icon-editor - rotate: false - xy: 331, 382 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -door-large-open - rotate: false - xy: 727, 363 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -phase-wall-large - rotate: false - xy: 265, 250 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -phase-wall-large-icon-editor - rotate: false - xy: 265, 250 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -scrap-wall-huge1 - rotate: false - xy: 99, 627 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -scrap-wall-huge-icon-editor - rotate: false - xy: 99, 627 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -scrap-wall-huge2 - rotate: false - xy: 197, 627 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -scrap-wall-huge3 - rotate: false - xy: 295, 627 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -scrap-wall-large1 - rotate: false - xy: 331, 118 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -scrap-wall-large2 - rotate: false - xy: 727, 99 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -scrap-wall-large3 - rotate: false - xy: 793, 99 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -scrap-wall-large4 - rotate: false - xy: 859, 99 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -surge-wall-large - rotate: false - xy: 397, 25 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -surge-wall-large-icon-editor - rotate: false - xy: 397, 25 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -thorium-wall-large - rotate: false - xy: 67, 1 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -thorium-wall-large-icon-editor - rotate: false - xy: 67, 1 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -crawler-factory-icon-editor - rotate: false - xy: 67, 463 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -cryofluidmixer-icon-editor - rotate: false - xy: 331, 448 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -cultivator-icon-editor - rotate: false - xy: 397, 421 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -dagger-factory-icon-editor - rotate: false - xy: 661, 421 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -lancer-icon-editor - rotate: false - xy: 265, 316 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -laser-drill-icon-editor - rotate: false - xy: 197, 921 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -liquid-tank-icon-editor - rotate: false - xy: 883, 921 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -mass-driver-icon-editor - rotate: false - xy: 491, 823 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -mechanical-drill-icon-editor - rotate: false - xy: 793, 297 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -oil-extractor-icon-editor - rotate: false - xy: 883, 823 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -phantom-factory-icon-editor - rotate: false - xy: 67, 265 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -phase-weaver-icon-editor - rotate: false - xy: 793, 231 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -pneumatic-drill-icon-editor - rotate: false - xy: 595, 223 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -power-node-large-icon-editor - rotate: false - xy: 199, 199 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -ripple-icon-editor - rotate: false - xy: 785, 725 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -salvo-icon-editor - rotate: false - xy: 595, 157 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -scatter-icon-editor - rotate: false - xy: 199, 133 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -scrap-wall-large-icon-editor - rotate: false - xy: 925, 99 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -spirit-factory-icon-editor - rotate: false - xy: 595, 91 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -spore-press-icon-editor - rotate: false - xy: 331, 52 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -swarmer-icon-editor - rotate: false - xy: 529, 25 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -titan-factory-icon-editor - rotate: false - xy: 1, 529 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -laser-end - rotate: false - xy: 541, 553 - size: 72, 72 - orig: 72, 72 - offset: 0, 0 - index: -1 -minelaser-end - rotate: false - xy: 615, 553 - size: 72, 72 - orig: 72, 72 - offset: 0, 0 - index: -1 -transfer-end - rotate: false - xy: 689, 553 - size: 72, 72 - orig: 72, 72 - offset: 0, 0 - index: -1 -cracks-2-0 - rotate: false - xy: 763, 495 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -cracks-2-1 - rotate: false - xy: 829, 495 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -cracks-2-2 - rotate: false - xy: 895, 495 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -cracks-2-3 - rotate: false - xy: 427, 487 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -cracks-2-4 - rotate: false - xy: 493, 487 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -cracks-2-5 - rotate: false - xy: 559, 487 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -cracks-2-6 - rotate: false - xy: 625, 487 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -cracks-2-7 - rotate: false - xy: 691, 487 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -crawler-factory-icon-full - rotate: false - xy: 133, 463 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -cryofluidmixer-icon-full - rotate: false - xy: 757, 429 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -cultivator-icon-full - rotate: false - xy: 463, 421 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -dagger-factory-icon-full - rotate: false - xy: 1, 397 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -lancer - rotate: false - xy: 133, 331 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -lancer-icon-full - rotate: false - xy: 331, 316 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -laser-drill-icon-full - rotate: false - xy: 295, 921 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -liquid-tank-icon-full - rotate: false - xy: 1, 823 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -mass-driver - rotate: false - xy: 295, 823 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -mass-driver-icon-full - rotate: false - xy: 589, 823 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -mechanical-drill-icon-full - rotate: false - xy: 859, 297 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -oil-extractor-icon-full - rotate: false - xy: 1, 725 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -phantom-factory-icon-full - rotate: false - xy: 133, 265 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -phase-weaver-icon-full - rotate: false - xy: 859, 231 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -pneumatic-drill-icon-full - rotate: false - xy: 661, 223 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -ripple - rotate: false - xy: 589, 725 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -ripple-icon-full - rotate: false - xy: 883, 725 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -salvo - rotate: false - xy: 463, 157 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -salvo-icon-full - rotate: false - xy: 661, 157 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -scatter - rotate: false - xy: 133, 133 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -scatter-icon-full - rotate: false - xy: 265, 118 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -spirit-factory-icon-full - rotate: false - xy: 661, 91 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -spore-press-icon-full - rotate: false - xy: 727, 33 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -swarmer - rotate: false - xy: 463, 25 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -swarmer-icon-full - rotate: false - xy: 595, 25 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -titan-factory-icon-full - rotate: false - xy: 99, 529 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -omega-mech-armor - rotate: false - xy: 595, 289 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -discord-banner - rotate: false - xy: 295, 580 - size: 84, 45 - orig: 84, 45 - offset: 0, 0 - index: -1 -info-banner - rotate: false - xy: 381, 580 - size: 84, 45 - orig: 84, 45 - offset: 0, 0 - index: -1 -eruptor - rotate: false - xy: 793, 363 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -eruptor-base - rotate: false - xy: 859, 363 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -eruptor-leg - rotate: false - xy: 925, 363 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -fortress - rotate: false - xy: 397, 355 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -fortress-base - rotate: false - xy: 463, 355 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -titan-base - rotate: false - xy: 463, 355 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -fortress-leg - rotate: false - xy: 529, 355 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -ghoul - rotate: false - xy: 467, 553 - size: 72, 72 - orig: 72, 72 - offset: 0, 0 - index: -1 -titan - rotate: false - xy: 133, 1 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -titan-leg - rotate: false - xy: 199, 1 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 - -sprites_fallback4.png -size: 1024,1024 -format: RGBA8888 -filter: Nearest,Nearest -repeat: none -bridge-conveyor - rotate: false - xy: 797, 106 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -bridge-conveyor-icon-editor - rotate: false - xy: 797, 106 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -bridge-conveyor-bridge - rotate: false - xy: 893, 634 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -bridge-conveyor-end - rotate: false - xy: 927, 618 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -center - rotate: false - xy: 961, 618 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conveyor-0-0 - rotate: false - xy: 339, 82 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conveyor-icon-editor - rotate: false - xy: 339, 82 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conveyor-0-1 - rotate: false - xy: 373, 116 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conveyor-0-2 - rotate: false - xy: 339, 48 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conveyor-0-3 - rotate: false - xy: 373, 82 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conveyor-1-0 - rotate: false - xy: 407, 116 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conveyor-1-1 - rotate: false - xy: 373, 48 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conveyor-1-2 - rotate: false - xy: 407, 82 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conveyor-1-3 - rotate: false - xy: 441, 116 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conveyor-2-0 - rotate: false - xy: 407, 48 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conveyor-2-1 - rotate: false - xy: 441, 82 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conveyor-2-2 - rotate: false - xy: 475, 116 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conveyor-2-3 - rotate: false - xy: 441, 48 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conveyor-3-0 - rotate: false - xy: 475, 82 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conveyor-3-1 - rotate: false - xy: 509, 116 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conveyor-3-2 - rotate: false - xy: 475, 48 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conveyor-3-3 - rotate: false - xy: 509, 82 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conveyor-4-0 - rotate: false - xy: 543, 116 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conveyor-4-1 - rotate: false - xy: 509, 48 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conveyor-4-2 - rotate: false - xy: 543, 82 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conveyor-4-3 - rotate: false - xy: 543, 48 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -water-extractor - rotate: false - xy: 67, 825 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -water-extractor-liquid - rotate: false - xy: 1, 693 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -water-extractor-rotator - rotate: false - xy: 67, 759 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -water-extractor-top - rotate: false - xy: 133, 825 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -block-border - rotate: false - xy: 797, 344 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -block-border-editor - rotate: false - xy: 797, 344 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -block-middle - rotate: false - xy: 797, 310 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -pump-liquid - rotate: false - xy: 797, 310 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -block-select - rotate: false - xy: 797, 276 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conduit-liquid - rotate: false - xy: 237, 82 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -bridge-conduit - rotate: false - xy: 797, 242 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -bridge-conduit-icon-editor - rotate: false - xy: 797, 242 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -bridge-conduit-arrow - rotate: false - xy: 797, 208 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -bridge-conveyor-arrow - rotate: false - xy: 797, 208 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -bridge-conduit-bridge - rotate: false - xy: 797, 174 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -bridge-conduit-end - rotate: false - xy: 797, 140 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conduit-bottom - rotate: false - xy: 135, 57 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conduit-bottom-0 - rotate: false - xy: 169, 91 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conduit-bottom-1 - rotate: false - xy: 135, 23 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conduit-bottom-2 - rotate: false - xy: 169, 57 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conduit-bottom-3 - rotate: false - xy: 169, 23 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conduit-bottom-4 - rotate: false - xy: 203, 125 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conduit-bottom-5 - rotate: false - xy: 203, 91 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conduit-bottom-6 - rotate: false - xy: 203, 57 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conduit-top-0 - rotate: false - xy: 271, 116 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conduit-top-1 - rotate: false - xy: 237, 48 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conduit-top-2 - rotate: false - xy: 271, 82 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conduit-top-3 - rotate: false - xy: 305, 116 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conduit-top-4 - rotate: false - xy: 271, 48 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conduit-top-5 - rotate: false - xy: 305, 82 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conduit-top-6 - rotate: false - xy: 339, 116 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -trident-ship-pad - rotate: false - xy: 1, 891 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -trident-ship-pad-icon-editor - rotate: false - xy: 1, 891 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -battery - rotate: false - xy: 797, 514 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -battery-icon-editor - rotate: false - xy: 797, 514 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -combustion-generator - rotate: false - xy: 169, 125 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -combustion-generator-icon-editor - rotate: false - xy: 169, 125 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -combustion-generator-top - rotate: false - xy: 135, 91 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -turbine-generator - rotate: false - xy: 67, 957 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -turbine-generator-icon-editor - rotate: false - xy: 67, 957 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -turbine-generator-top - rotate: false - xy: 1, 825 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -arc-heat - rotate: false - xy: 989, 879 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -block-1 - rotate: false - xy: 797, 378 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -hail-heat - rotate: false - xy: 982, 981 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -wave-liquid - rotate: false - xy: 67, 693 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -wraith-factory-top - rotate: false - xy: 265, 891 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -copper-wall - rotate: false - xy: 237, 14 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -copper-wall-icon-editor - rotate: false - xy: 237, 14 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -door - rotate: false - xy: 831, 584 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -door-icon-editor - rotate: false - xy: 831, 584 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -door-open - rotate: false - xy: 831, 516 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium-wall-large - rotate: false - xy: 1, 957 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -titanium-wall-large-icon-editor - rotate: false - xy: 1, 957 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -arc-icon-editor - rotate: false - xy: 797, 582 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -char-icon-editor - rotate: false - xy: 101, 193 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-char1 - rotate: false - xy: 101, 193 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -cliffs-icon-editor - rotate: false - xy: 135, 125 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conduit-icon-editor - rotate: false - xy: 203, 23 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -craters-icon-editor - rotate: false - xy: 611, 47 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-craters1 - rotate: false - xy: 611, 47 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -dark-metal-icon-editor - rotate: false - xy: 713, 47 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -dark-panel-1-icon-editor - rotate: false - xy: 577, 13 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-dark-panel-1 - rotate: false - xy: 577, 13 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -dark-panel-2-icon-editor - rotate: false - xy: 611, 13 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-dark-panel-2 - rotate: false - xy: 611, 13 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -dark-panel-3-icon-editor - rotate: false - xy: 645, 13 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-dark-panel-3 - rotate: false - xy: 645, 13 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -dark-panel-4-icon-editor - rotate: false - xy: 679, 13 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-dark-panel-4 - rotate: false - xy: 679, 13 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -dark-panel-5-icon-editor - rotate: false - xy: 713, 13 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-dark-panel-5 - rotate: false - xy: 713, 13 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -dark-panel-6-icon-editor - rotate: false - xy: 747, 81 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-dark-panel-6 - rotate: false - xy: 747, 81 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -darksand-icon-editor - rotate: false - xy: 747, 47 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-darksand1 - rotate: false - xy: 747, 47 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -darksand-tainted-water-icon-editor - rotate: false - xy: 747, 13 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-darksand-tainted-water - rotate: false - xy: 747, 13 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -darksand-water-icon-editor - rotate: false - xy: 781, 72 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-darksand-water - rotate: false - xy: 781, 72 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -deepwater-icon-editor - rotate: false - xy: 781, 4 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-deepwater - rotate: false - xy: 781, 4 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -dunerocks-icon-editor - rotate: false - xy: 831, 482 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -duo-icon-editor - rotate: false - xy: 831, 414 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-char2 - rotate: false - xy: 831, 346 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-char3 - rotate: false - xy: 831, 312 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-craters2 - rotate: false - xy: 831, 278 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-craters3 - rotate: false - xy: 831, 244 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-darksand2 - rotate: false - xy: 831, 210 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-darksand3 - rotate: false - xy: 831, 176 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-grass1 - rotate: false - xy: 831, 142 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -grass-icon-editor - rotate: false - xy: 831, 142 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-grass2 - rotate: false - xy: 831, 108 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-grass3 - rotate: false - xy: 865, 600 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-holostone1 - rotate: false - xy: 865, 566 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -holostone-icon-editor - rotate: false - xy: 865, 566 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-holostone2 - rotate: false - xy: 865, 532 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-holostone3 - rotate: false - xy: 865, 498 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-hotrock1 - rotate: false - xy: 865, 464 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -hotrock-icon-editor - rotate: false - xy: 865, 464 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-hotrock2 - rotate: false - xy: 865, 430 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-hotrock3 - rotate: false - xy: 865, 396 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-ice-snow1 - rotate: false - xy: 865, 260 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ice-snow-icon-editor - rotate: false - xy: 865, 260 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-ice-snow2 - rotate: false - xy: 865, 226 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-ice-snow3 - rotate: false - xy: 865, 192 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-ice1 - rotate: false - xy: 865, 362 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ice-icon-editor - rotate: false - xy: 865, 362 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-ice2 - rotate: false - xy: 865, 328 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-ice3 - rotate: false - xy: 865, 294 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-ignarock1 - rotate: false - xy: 865, 158 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ignarock-icon-editor - rotate: false - xy: 865, 158 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-ignarock2 - rotate: false - xy: 865, 124 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-ignarock3 - rotate: false - xy: 865, 90 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-magmarock1 - rotate: false - xy: 849, 56 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -magmarock-icon-editor - rotate: false - xy: 849, 56 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-magmarock2 - rotate: false - xy: 849, 22 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-magmarock3 - rotate: false - xy: 883, 56 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-metal-floor - rotate: false - xy: 883, 22 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -metal-floor-icon-editor - rotate: false - xy: 883, 22 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-metal-floor-2 - rotate: false - xy: 899, 584 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -metal-floor-2-icon-editor - rotate: false - xy: 899, 584 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-metal-floor-3 - rotate: false - xy: 899, 550 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -metal-floor-3-icon-editor - rotate: false - xy: 899, 550 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-metal-floor-5 - rotate: false - xy: 933, 584 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -metal-floor-5-icon-editor - rotate: false - xy: 933, 584 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-metal-floor-damaged1 - rotate: false - xy: 899, 516 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -metal-floor-damaged-icon-editor - rotate: false - xy: 899, 516 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-metal-floor-damaged2 - rotate: false - xy: 933, 550 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-metal-floor-damaged3 - rotate: false - xy: 899, 482 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-moss1 - rotate: false - xy: 933, 516 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -moss-icon-editor - rotate: false - xy: 933, 516 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-moss2 - rotate: false - xy: 899, 448 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-moss3 - rotate: false - xy: 933, 482 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-ore-coal1 - rotate: false - xy: 899, 414 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-ore-coal2 - rotate: false - xy: 933, 448 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-ore-coal3 - rotate: false - xy: 899, 380 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-ore-copper1 - rotate: false - xy: 933, 414 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-ore-copper2 - rotate: false - xy: 899, 346 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-ore-copper3 - rotate: false - xy: 933, 380 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-ore-lead1 - rotate: false - xy: 899, 312 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-ore-lead2 - rotate: false - xy: 933, 346 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-ore-lead3 - rotate: false - xy: 899, 278 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-ore-scrap1 - rotate: false - xy: 933, 312 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-ore-scrap2 - rotate: false - xy: 899, 244 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-ore-scrap3 - rotate: false - xy: 933, 278 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-ore-thorium1 - rotate: false - xy: 899, 210 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-ore-thorium2 - rotate: false - xy: 933, 244 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-ore-thorium3 - rotate: false - xy: 899, 176 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-ore-titanium1 - rotate: false - xy: 933, 210 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-ore-titanium2 - rotate: false - xy: 899, 142 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-ore-titanium3 - rotate: false - xy: 933, 176 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-pebbles1 - rotate: false - xy: 899, 108 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-pebbles2 - rotate: false - xy: 933, 142 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-pebbles3 - rotate: false - xy: 933, 108 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-salt - rotate: false - xy: 967, 584 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -salt-icon-editor - rotate: false - xy: 967, 584 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-sand-water - rotate: false - xy: 967, 448 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -sand-water-icon-editor - rotate: false - xy: 967, 448 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-sand1 - rotate: false - xy: 967, 550 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -sand-icon-editor - rotate: false - xy: 967, 550 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-sand2 - rotate: false - xy: 967, 516 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-sand3 - rotate: false - xy: 967, 482 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-shale1 - rotate: false - xy: 967, 414 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -shale-icon-editor - rotate: false - xy: 967, 414 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-shale2 - rotate: false - xy: 967, 380 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-shale3 - rotate: false - xy: 967, 346 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-snow1 - rotate: false - xy: 967, 312 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -snow-icon-editor - rotate: false - xy: 967, 312 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-snow2 - rotate: false - xy: 967, 278 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-snow3 - rotate: false - xy: 967, 244 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-spawn - rotate: false - xy: 967, 210 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-spore-moss1 - rotate: false - xy: 967, 176 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -spore-moss-icon-editor - rotate: false - xy: 967, 176 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-spore-moss2 - rotate: false - xy: 967, 142 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-spore-moss3 - rotate: false - xy: 967, 108 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-stone1 - rotate: false - xy: 917, 74 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -stone-icon-editor - rotate: false - xy: 917, 74 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-stone2 - rotate: false - xy: 917, 40 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-stone3 - rotate: false - xy: 951, 74 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-tainted-water - rotate: false - xy: 951, 40 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -tainted-water-icon-editor - rotate: false - xy: 951, 40 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-tar - rotate: false - xy: 917, 6 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -tar-icon-editor - rotate: false - xy: 917, 6 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-tendrils1 - rotate: false - xy: 951, 6 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-tendrils2 - rotate: false - xy: 985, 74 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-tendrils3 - rotate: false - xy: 985, 40 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -editor-water - rotate: false - xy: 985, 6 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -water-icon-editor - rotate: false - xy: 985, 6 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -pine-icon-editor - rotate: false - xy: 409, 150 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -rock-icon-editor - rotate: false - xy: 559, 550 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -snowrock-icon-editor - rotate: false - xy: 607, 765 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -spore-cluster-icon-editor - rotate: false - xy: 893, 697 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -spore-pine-icon-editor - rotate: false - xy: 609, 215 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -water-extractor-icon-editor - rotate: false - xy: 133, 891 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -wave-icon-editor - rotate: false - xy: 265, 957 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -wraith-factory-icon-editor - rotate: false - xy: 133, 759 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -bullet - rotate: false - xy: 1, 261 - size: 52, 52 - orig: 52, 52 - offset: 0, 0 - index: -1 -bullet-back - rotate: false - xy: 628, 969 - size: 52, 52 - orig: 52, 52 - offset: 0, 0 - index: -1 -error - rotate: false - xy: 475, 650 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -missile - rotate: false - xy: 759, 346 - size: 36, 36 - orig: 36, 36 - offset: 0, 0 - index: -1 -missile-back - rotate: false - xy: 759, 308 - size: 36, 36 - orig: 36, 36 - offset: 0, 0 - index: -1 -shell - rotate: false - xy: 759, 212 - size: 36, 36 - orig: 36, 36 - offset: 0, 0 - index: -1 -shell-back - rotate: false - xy: 759, 174 - size: 36, 36 - orig: 36, 36 - offset: 0, 0 - index: -1 -alloy-smelter-icon-large - rotate: false - xy: 1, 211 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -alloy-smelter-icon-medium - rotate: false - xy: 989, 947 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -arc - rotate: false - xy: 989, 913 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -arc-icon-full - rotate: false - xy: 797, 548 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -arc-icon-large - rotate: false - xy: 1, 111 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -battery-icon-large - rotate: false - xy: 782, 973 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -battery-large-icon-large - rotate: false - xy: 1, 3 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -battery-large-icon-medium - rotate: false - xy: 797, 480 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -blast-drill-icon-large - rotate: false - xy: 832, 973 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -blast-drill-icon-medium - rotate: false - xy: 797, 446 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -blast-mixer-icon-large - rotate: false - xy: 882, 973 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -blast-mixer-icon-medium - rotate: false - xy: 797, 412 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -bridge-conduit-icon-large - rotate: false - xy: 323, 800 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -bridge-conveyor-icon-large - rotate: false - xy: 59, 577 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -char-icon-large - rotate: false - xy: 59, 477 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -cliffs-icon-large - rotate: false - xy: 59, 427 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -coal-centrifuge-icon-large - rotate: false - xy: 59, 377 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -coal-centrifuge-icon-medium - rotate: false - xy: 169, 159 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -combustion-generator-icon-large - rotate: false - xy: 59, 327 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -conduit-icon-full - rotate: false - xy: 237, 116 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conduit-icon-large - rotate: false - xy: 59, 277 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -container-icon-large - rotate: false - xy: 55, 227 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -container-icon-medium - rotate: false - xy: 305, 48 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -conveyor-icon-large - rotate: false - xy: 51, 177 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -copper-wall-icon-large - rotate: false - xy: 51, 127 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -copper-wall-large-icon-large - rotate: false - xy: 51, 77 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -copper-wall-large-icon-medium - rotate: false - xy: 271, 14 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -core-foundation-icon-large - rotate: false - xy: 51, 27 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -core-foundation-icon-medium - rotate: false - xy: 305, 14 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -core-nucleus-icon-large - rotate: false - xy: 125, 643 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -core-nucleus-icon-medium - rotate: false - xy: 339, 14 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -core-shard-icon-large - rotate: false - xy: 191, 709 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -core-shard-icon-medium - rotate: false - xy: 373, 14 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -cracks-1-0 - rotate: false - xy: 407, 14 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -cracks-1-1 - rotate: false - xy: 441, 14 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -cracks-1-2 - rotate: false - xy: 475, 14 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -cracks-1-3 - rotate: false - xy: 509, 14 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -cracks-1-4 - rotate: false - xy: 543, 14 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -cracks-1-5 - rotate: false - xy: 577, 81 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -cracks-1-6 - rotate: false - xy: 577, 47 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -cracks-1-7 - rotate: false - xy: 611, 81 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -craters-icon-large - rotate: false - xy: 381, 850 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -crawler-factory-icon-large - rotate: false - xy: 307, 750 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -crawler-factory-icon-medium - rotate: false - xy: 645, 81 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -cryofluidmixer-icon-large - rotate: false - xy: 257, 725 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -cryofluidmixer-icon-medium - rotate: false - xy: 645, 47 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -cultivator-icon-large - rotate: false - xy: 307, 700 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -cultivator-icon-medium - rotate: false - xy: 679, 81 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -cyclone-icon-large - rotate: false - xy: 357, 700 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -cyclone-icon-medium - rotate: false - xy: 679, 47 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -dagger-factory-icon-large - rotate: false - xy: 423, 800 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -dagger-factory-icon-medium - rotate: false - xy: 713, 81 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -dark-metal-icon-large - rotate: false - xy: 457, 700 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -dark-panel-1-icon-large - rotate: false - xy: 109, 585 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -dark-panel-2-icon-large - rotate: false - xy: 109, 535 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -dark-panel-3-icon-large - rotate: false - xy: 109, 485 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -dark-panel-4-icon-large - rotate: false - xy: 109, 435 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -dark-panel-5-icon-large - rotate: false - xy: 109, 385 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -dark-panel-6-icon-large - rotate: false - xy: 109, 335 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -darksand-icon-large - rotate: false - xy: 109, 285 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -darksand-tainted-water-icon-large - rotate: false - xy: 175, 651 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -darksand-water-icon-large - rotate: false - xy: 159, 593 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -dart-mech-pad-icon-large - rotate: false - xy: 159, 543 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -dart-mech-pad-icon-medium - rotate: false - xy: 781, 38 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -deepwater-icon-large - rotate: false - xy: 159, 443 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -delta-mech-pad-icon-large - rotate: false - xy: 109, 235 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -delta-mech-pad-icon-medium - rotate: false - xy: 815, 72 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -differential-generator-icon-large - rotate: false - xy: 159, 243 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -differential-generator-icon-medium - rotate: false - xy: 815, 38 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -distributor-icon-large - rotate: false - xy: 225, 659 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -distributor-icon-medium - rotate: false - xy: 815, 4 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -door-icon-large - rotate: false - xy: 275, 650 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -door-large-icon-large - rotate: false - xy: 325, 650 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -door-large-icon-medium - rotate: false - xy: 831, 550 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -dunerocks-icon-large - rotate: false - xy: 375, 650 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -duo - rotate: false - xy: 831, 448 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -duo-icon-full - rotate: false - xy: 831, 380 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -duo-icon-large - rotate: false - xy: 425, 650 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -force-projector-icon-large - rotate: false - xy: 489, 915 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -fortress-factory-icon-large - rotate: false - xy: 539, 915 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -fuse-icon-large - rotate: false - xy: 473, 800 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ghoul-factory-icon-large - rotate: false - xy: 589, 915 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -glaive-ship-pad-icon-large - rotate: false - xy: 639, 919 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -graphite-press-icon-large - rotate: false - xy: 689, 923 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -grass-icon-large - rotate: false - xy: 739, 923 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -hail-icon-large - rotate: false - xy: 789, 923 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -holostone-icon-large - rotate: false - xy: 889, 923 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -hotrock-icon-large - rotate: false - xy: 939, 923 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ice-icon-large - rotate: false - xy: 225, 609 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ice-snow-icon-large - rotate: false - xy: 275, 600 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -icerocks-icon-large - rotate: false - xy: 325, 600 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ignarock-icon-large - rotate: false - xy: 425, 600 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -impact-reactor-icon-large - rotate: false - xy: 475, 600 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -incinerator-icon-large - rotate: false - xy: 209, 559 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -item-blast-compound-xlarge - rotate: false - xy: 857, 781 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -item-coal-xlarge - rotate: false - xy: 801, 731 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -item-copper-xlarge - rotate: false - xy: 899, 781 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -item-graphite-xlarge - rotate: false - xy: 941, 781 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -item-lead-xlarge - rotate: false - xy: 983, 781 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -item-metaglass-xlarge - rotate: false - xy: 725, 677 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -item-phase-fabric-xlarge - rotate: false - xy: 725, 635 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -item-plastanium-xlarge - rotate: false - xy: 767, 687 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -item-pyratite-xlarge - rotate: false - xy: 767, 645 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -item-sand-xlarge - rotate: false - xy: 809, 689 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -item-scrap-xlarge - rotate: false - xy: 809, 647 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -item-silicon-xlarge - rotate: false - xy: 843, 731 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -item-source-icon-large - rotate: false - xy: 209, 509 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -item-spore-pod-xlarge - rotate: false - xy: 885, 739 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -item-surge-alloy-xlarge - rotate: false - xy: 927, 739 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -item-thorium-xlarge - rotate: false - xy: 969, 739 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -item-titanium-xlarge - rotate: false - xy: 851, 689 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -item-void-icon-large - rotate: false - xy: 209, 459 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -javelin-ship-pad-icon-large - rotate: false - xy: 209, 359 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -junction-icon-large - rotate: false - xy: 209, 259 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -kiln-icon-large - rotate: false - xy: 259, 550 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -lancer-icon-large - rotate: false - xy: 259, 500 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -laser-drill-icon-large - rotate: false - xy: 309, 550 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -launch-pad-icon-large - rotate: false - xy: 259, 450 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -launch-pad-large-icon-large - rotate: false - xy: 309, 500 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -liquid-junction-icon-large - rotate: false - xy: 259, 400 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -liquid-router-icon-large - rotate: false - xy: 309, 450 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -liquid-source-icon-large - rotate: false - xy: 359, 500 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -liquid-tank-icon-large - rotate: false - xy: 409, 550 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -magmarock-icon-large - rotate: false - xy: 259, 350 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -mass-driver-icon-large - rotate: false - xy: 309, 400 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -mech-icon-alpha-mech - rotate: false - xy: 359, 450 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -mech-icon-dart-ship - rotate: false - xy: 409, 500 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -mech-icon-delta-mech - rotate: false - xy: 459, 550 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -mech-icon-glaive-ship - rotate: false - xy: 133, 701 - size: 56, 56 - orig: 56, 56 - offset: 0, 0 - index: -1 -mech-icon-javelin-ship - rotate: false - xy: 259, 300 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -mech-icon-omega-mech - rotate: false - xy: 199, 767 - size: 56, 56 - orig: 56, 56 - offset: 0, 0 - index: -1 -mech-icon-tau-mech - rotate: false - xy: 265, 833 - size: 56, 56 - orig: 56, 56 - offset: 0, 0 - index: -1 -mech-icon-trident-ship - rotate: false - xy: 331, 900 - size: 56, 56 - orig: 56, 56 - offset: 0, 0 - index: -1 -mechanical-drill-icon-large - rotate: false - xy: 309, 350 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -mechanical-pump-icon-large - rotate: false - xy: 359, 400 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -meltdown-icon-large - rotate: false - xy: 409, 450 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -melter-icon-large - rotate: false - xy: 459, 500 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -mend-projector-icon-large - rotate: false - xy: 309, 300 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -mender-icon-large - rotate: false - xy: 359, 350 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -metal-floor-2-icon-large - rotate: false - xy: 409, 400 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -metal-floor-3-icon-large - rotate: false - xy: 459, 450 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -metal-floor-5-icon-large - rotate: false - xy: 359, 300 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -metal-floor-damaged-icon-large - rotate: false - xy: 409, 350 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -metal-floor-icon-large - rotate: false - xy: 459, 400 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -moss-icon-large - rotate: false - xy: 409, 300 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -multi-press-icon-large - rotate: false - xy: 459, 350 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -oil-extractor-icon-large - rotate: false - xy: 459, 300 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -omega-mech-pad-icon-large - rotate: false - xy: 259, 250 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-coal-icon-large - rotate: false - xy: 309, 250 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-copper-icon-large - rotate: false - xy: 359, 250 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-lead-icon-large - rotate: false - xy: 409, 250 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-scrap-icon-large - rotate: false - xy: 459, 250 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-thorium-icon-large - rotate: false - xy: 209, 209 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ore-titanium-icon-large - rotate: false - xy: 159, 193 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -overdrive-projector-icon-large - rotate: false - xy: 259, 200 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -overflow-gate-icon-large - rotate: false - xy: 309, 200 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -pebbles-icon-large - rotate: false - xy: 359, 200 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -phantom-factory-icon-large - rotate: false - xy: 409, 200 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -phase-conduit-icon-large - rotate: false - xy: 459, 200 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -phase-conveyor-icon-large - rotate: false - xy: 209, 159 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -phase-wall-icon-large - rotate: false - xy: 259, 150 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -phase-wall-large-icon-large - rotate: false - xy: 309, 150 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -phase-weaver-icon-large - rotate: false - xy: 359, 150 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -plastanium-compressor-icon-large - rotate: false - xy: 459, 150 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -pneumatic-drill-icon-large - rotate: false - xy: 507, 750 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -power-node-icon-large - rotate: false - xy: 507, 700 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -power-node-large-icon-large - rotate: false - xy: 525, 650 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -power-source-icon-large - rotate: false - xy: 525, 600 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -power-void-icon-large - rotate: false - xy: 509, 550 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -pulse-conduit-icon-large - rotate: false - xy: 509, 500 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -pulverizer-icon-large - rotate: false - xy: 509, 450 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -pyratite-mixer-icon-large - rotate: false - xy: 509, 400 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -repair-point-icon-large - rotate: false - xy: 509, 300 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -revenant-factory-icon-large - rotate: false - xy: 509, 250 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -ripple-icon-large - rotate: false - xy: 509, 150 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -rocks-icon-large - rotate: false - xy: 559, 500 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -rotary-pump-icon-large - rotate: false - xy: 559, 450 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -router-icon-large - rotate: false - xy: 559, 400 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -rtg-generator-icon-large - rotate: false - xy: 559, 350 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -salt-icon-large - rotate: false - xy: 559, 300 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -saltrocks-icon-large - rotate: false - xy: 559, 250 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -salvo-icon-large - rotate: false - xy: 559, 200 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -sand-icon-large - rotate: false - xy: 559, 150 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -sand-water-icon-large - rotate: false - xy: 489, 865 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -sandrocks-icon-large - rotate: false - xy: 539, 865 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -scatter-icon-large - rotate: false - xy: 589, 865 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -scorch-icon-large - rotate: false - xy: 639, 869 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -scrap-wall-gigantic-icon-large - rotate: false - xy: 689, 873 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -scrap-wall-huge-icon-large - rotate: false - xy: 739, 873 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -scrap-wall-icon-large - rotate: false - xy: 789, 873 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -scrap-wall-large-icon-large - rotate: false - xy: 839, 873 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -separator-icon-large - rotate: false - xy: 889, 873 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -shale-boulder-icon-large - rotate: false - xy: 939, 873 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -shale-icon-large - rotate: false - xy: 523, 815 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -shalerocks-icon-large - rotate: false - xy: 573, 815 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -shock-mine-icon-large - rotate: false - xy: 557, 765 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -shrubs-icon-large - rotate: false - xy: 575, 665 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -silicon-smelter-icon-large - rotate: false - xy: 575, 615 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -snow-icon-large - rotate: false - xy: 623, 815 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -snowrocks-icon-large - rotate: false - xy: 607, 715 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -solar-panel-icon-large - rotate: false - xy: 625, 665 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -solar-panel-large-icon-large - rotate: false - xy: 625, 615 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -sorter-icon-large - rotate: false - xy: 609, 565 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -spawn-icon-large - rotate: false - xy: 609, 515 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -spectre-icon-large - rotate: false - xy: 609, 465 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -spirit-factory-icon-large - rotate: false - xy: 609, 365 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -spore-cluster-icon-large - rotate: false - xy: 609, 315 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -spore-moss-icon-large - rotate: false - xy: 609, 265 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -spore-press-icon-large - rotate: false - xy: 609, 165 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -sporerocks-icon-large - rotate: false - xy: 657, 765 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -stone-icon-large - rotate: false - xy: 657, 715 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -surge-tower-icon-large - rotate: false - xy: 675, 665 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -surge-wall-icon-large - rotate: false - xy: 675, 615 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -surge-wall-large-icon-large - rotate: false - xy: 659, 565 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -swarmer-icon-large - rotate: false - xy: 659, 465 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -tainted-water-icon-large - rotate: false - xy: 659, 415 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -tar-icon-large - rotate: false - xy: 659, 365 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -tau-mech-pad-icon-large - rotate: false - xy: 659, 215 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -tendrils-icon-large - rotate: false - xy: 659, 165 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -thermal-generator-icon-large - rotate: false - xy: 709, 565 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -thermal-pump-icon-large - rotate: false - xy: 709, 515 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -thorium-reactor-icon-large - rotate: false - xy: 709, 465 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -thorium-wall-icon-large - rotate: false - xy: 709, 415 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -thorium-wall-large-icon-large - rotate: false - xy: 709, 365 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -thruster-icon-large - rotate: false - xy: 709, 315 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -titan-factory-icon-large - rotate: false - xy: 709, 265 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -titanium-conveyor-icon-large - rotate: false - xy: 709, 215 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -titanium-wall-icon-large - rotate: false - xy: 709, 165 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -titanium-wall-large-icon-large - rotate: false - xy: 609, 115 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -trident-ship-pad-icon-large - rotate: false - xy: 659, 115 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -turbine-generator-icon-large - rotate: false - xy: 709, 115 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -unit-icon-crawler - rotate: false - xy: 673, 819 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -unit-icon-dagger - rotate: false - xy: 723, 823 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -unit-icon-eruptor - rotate: false - xy: 67, 891 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -unit-icon-fortress - rotate: false - xy: 133, 957 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -unit-icon-titan - rotate: false - xy: 1, 759 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -unloader-icon-large - rotate: false - xy: 773, 823 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -vault-icon-large - rotate: false - xy: 823, 823 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -water-extractor-icon-full - rotate: false - xy: 199, 957 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -water-extractor-icon-large - rotate: false - xy: 873, 823 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -water-icon-large - rotate: false - xy: 923, 823 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -wave - rotate: false - xy: 199, 891 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -wave-icon-full - rotate: false - xy: 1, 627 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -wave-icon-large - rotate: false - xy: 973, 823 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -white-tree-dead-icon-large - rotate: false - xy: 707, 769 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -white-tree-icon-large - rotate: false - xy: 707, 719 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -wraith-factory-icon-full - rotate: false - xy: 199, 825 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -wraith-factory-icon-large - rotate: false - xy: 807, 773 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -alpha-mech - rotate: false - xy: 682, 973 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -alpha-mech-base - rotate: false - xy: 1, 161 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -alpha-mech-leg - rotate: false - xy: 732, 973 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -delta-mech - rotate: false - xy: 159, 393 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -delta-mech-base - rotate: false - xy: 159, 343 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -delta-mech-leg - rotate: false - xy: 159, 293 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -omega-mech - rotate: false - xy: 396, 965 - size: 56, 56 - orig: 56, 56 - offset: 0, 0 - index: -1 -omega-mech-base - rotate: false - xy: 1, 431 - size: 56, 56 - orig: 56, 56 - offset: 0, 0 - index: -1 -omega-mech-leg - rotate: false - xy: 454, 965 - size: 56, 56 - orig: 56, 56 - offset: 0, 0 - index: -1 -tau-mech - rotate: false - xy: 1, 315 - size: 56, 56 - orig: 56, 56 - offset: 0, 0 - index: -1 -tau-mech-base - rotate: false - xy: 659, 315 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -tau-mech-leg - rotate: false - xy: 659, 265 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -dart-ship - rotate: false - xy: 159, 493 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -glaive-ship - rotate: false - xy: 67, 635 - size: 56, 56 - orig: 56, 56 - offset: 0, 0 - index: -1 -javelin-ship - rotate: false - xy: 209, 409 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -javelin-ship-shield - rotate: false - xy: 209, 309 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -trident-ship - rotate: false - xy: 570, 965 - size: 56, 56 - orig: 56, 56 - offset: 0, 0 - index: -1 -shape-3 - rotate: false - xy: 331, 958 - size: 63, 63 - orig: 63, 63 - offset: 0, 0 - index: -1 -button - rotate: false - xy: 759, 500 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -button-disabled - rotate: false - xy: 893, 668 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -button-down - rotate: false - xy: 935, 710 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -button-edge-1 - rotate: false - xy: 973, 710 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -button-edge-2 - rotate: false - xy: 851, 634 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -button-edge-3 - rotate: false - xy: 935, 681 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -button-edge-4 - rotate: false - xy: 973, 681 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -button-over - rotate: false - xy: 767, 616 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -button-right - rotate: false - xy: 759, 529 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -button-right-down - rotate: false - xy: 759, 587 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -button-right-over - rotate: false - xy: 759, 558 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -check-disabled - rotate: false - xy: 101, 159 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -check-off - rotate: false - xy: 101, 125 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -check-on - rotate: false - xy: 101, 91 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -check-on-disabled - rotate: false - xy: 101, 57 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -check-on-over - rotate: false - xy: 101, 23 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -check-over - rotate: false - xy: 135, 159 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -content-background - rotate: false - xy: 759, 384 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -content-background-locked - rotate: false - xy: 759, 471 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -content-background-noitems - rotate: false - xy: 759, 442 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -content-background-over - rotate: false - xy: 759, 413 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -icon-generated - rotate: false - xy: 375, 600 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -icon-zone-locked - rotate: false - xy: 757, 729 - size: 42, 42 - orig: 42, 42 - offset: 0, 0 - index: -1 -pane - rotate: false - xy: 759, 250 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -pane-2 - rotate: false - xy: 759, 279 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -scroll-horizontal - rotate: false - xy: 51, 1 - size: 35, 24 - split: 6, 5, 10, 10 - orig: 35, 24 - offset: 0, 0 - index: -1 -scroll-knob-horizontal-black - rotate: false - xy: 851, 663 - size: 40, 24 - split: 11, 10, 10, 10 - orig: 40, 24 - offset: 0, 0 - index: -1 -underline - rotate: false - xy: 969, 652 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -underline-2 - rotate: false - xy: 759, 145 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -underline-disabled - rotate: false - xy: 759, 116 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -underline-red - rotate: false - xy: 931, 652 - size: 36, 27 - split: 12, 12, 12, 12 - orig: 36, 27 - offset: 0, 0 - index: -1 -crawler - rotate: false - xy: 373, 800 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -crawler-base - rotate: false - xy: 257, 775 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -crawler-leg - rotate: false - xy: 357, 750 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -dagger - rotate: false - xy: 407, 750 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -dagger-base - rotate: false - xy: 407, 700 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -dagger-leg - rotate: false - xy: 457, 750 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -phantom - rotate: false - xy: 1, 373 - size: 56, 56 - orig: 56, 56 - offset: 0, 0 - index: -1 -power-cell - rotate: false - xy: 512, 965 - size: 56, 56 - orig: 56, 56 - offset: 0, 0 - index: -1 -spirit - rotate: false - xy: 609, 415 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -wraith - rotate: false - xy: 757, 773 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -artillery-equip - rotate: false - xy: 1, 53 - size: 48, 56 - orig: 48, 56 - offset: 0, 0 - index: -1 -blaster-equip - rotate: false - xy: 932, 973 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -bomber-equip - rotate: false - xy: 331, 850 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -missiles-equip - rotate: false - xy: 331, 850 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -chain-blaster-equip - rotate: false - xy: 59, 527 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -chaos-equip - rotate: false - xy: 1, 489 - size: 56, 136 - orig: 56, 136 - offset: 0, 0 - index: -1 -eruption-equip - rotate: false - xy: 389, 900 - size: 48, 56 - orig: 48, 56 - offset: 0, 0 - index: -1 -flakgun-equip - rotate: false - xy: 431, 850 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -flamethrower-equip - rotate: false - xy: 439, 907 - size: 48, 56 - orig: 48, 56 - offset: 0, 0 - index: -1 -heal-blaster-equip - rotate: false - xy: 839, 923 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -lich-missiles-equip - rotate: false - xy: 359, 550 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -reaper-gun-equip - rotate: false - xy: 509, 350 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -revenant-missiles-equip - rotate: false - xy: 509, 200 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -shockgun-equip - rotate: false - xy: 557, 715 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -swarmer-equip - rotate: false - xy: 659, 515 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 - -sprites_fallback5.png -size: 1024,512 -format: RGBA8888 -filter: Nearest,Nearest -repeat: none -mender - rotate: false - xy: 137, 275 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -mender-icon-editor - rotate: false - xy: 137, 275 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -mender-top - rotate: false - xy: 171, 309 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -shock-mine - rotate: false - xy: 171, 105 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium-conveyor-0-0 - rotate: false - xy: 239, 105 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium-conveyor-icon-editor - rotate: false - xy: 239, 105 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium-conveyor-0-1 - rotate: false - xy: 273, 139 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium-conveyor-0-2 - rotate: false - xy: 307, 173 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium-conveyor-0-3 - rotate: false - xy: 341, 207 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium-conveyor-1-0 - rotate: false - xy: 375, 241 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium-conveyor-1-1 - rotate: false - xy: 409, 275 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium-conveyor-1-2 - rotate: false - xy: 443, 309 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium-conveyor-1-3 - rotate: false - xy: 477, 343 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium-conveyor-2-0 - rotate: false - xy: 511, 377 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium-conveyor-2-1 - rotate: false - xy: 545, 411 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium-conveyor-2-2 - rotate: false - xy: 579, 445 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium-conveyor-2-3 - rotate: false - xy: 613, 479 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium-conveyor-3-0 - rotate: false - xy: 171, 3 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium-conveyor-3-1 - rotate: false - xy: 205, 37 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium-conveyor-3-2 - rotate: false - xy: 239, 71 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium-conveyor-3-3 - rotate: false - xy: 273, 105 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium-conveyor-4-0 - rotate: false - xy: 307, 139 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium-conveyor-4-1 - rotate: false - xy: 341, 173 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium-conveyor-4-2 - rotate: false - xy: 375, 207 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium-conveyor-4-3 - rotate: false - xy: 409, 241 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -junction - rotate: false - xy: 239, 479 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -junction-icon-editor - rotate: false - xy: 239, 479 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -overflow-gate - rotate: false - xy: 171, 275 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -overflow-gate-icon-editor - rotate: false - xy: 171, 275 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -phase-conveyor - rotate: false - xy: 1, 71 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -phase-conveyor-icon-editor - rotate: false - xy: 1, 71 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -phase-conveyor-arrow - rotate: false - xy: 35, 105 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -phase-conveyor-bridge - rotate: false - xy: 69, 139 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -phase-conveyor-end - rotate: false - xy: 103, 173 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -router - rotate: false - xy: 375, 377 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -router-icon-editor - rotate: false - xy: 375, 377 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -sorter - rotate: false - xy: 477, 411 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -sorter-icon-editor - rotate: false - xy: 477, 411 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -liquid-junction - rotate: false - xy: 205, 411 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -liquid-junction-icon-editor - rotate: false - xy: 205, 411 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -liquid-router-bottom - rotate: false - xy: 273, 479 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -liquid-router-liquid - rotate: false - xy: 69, 241 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -liquid-router-top - rotate: false - xy: 103, 275 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -mechanical-pump - rotate: false - xy: 1, 139 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -mechanical-pump-icon-editor - rotate: false - xy: 1, 139 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -phase-conduit - rotate: false - xy: 273, 377 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -phase-conduit-icon-editor - rotate: false - xy: 273, 377 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -phase-conduit-arrow - rotate: false - xy: 307, 411 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -phase-conduit-bridge - rotate: false - xy: 341, 445 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -phase-conduit-end - rotate: false - xy: 375, 479 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -pulse-conduit-top-0 - rotate: false - xy: 137, 173 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -pulse-conduit-top-1 - rotate: false - xy: 171, 207 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -pulse-conduit-top-2 - rotate: false - xy: 205, 241 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -pulse-conduit-top-3 - rotate: false - xy: 239, 275 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -pulse-conduit-top-4 - rotate: false - xy: 273, 309 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -pulse-conduit-top-5 - rotate: false - xy: 307, 343 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -pulse-conduit-top-6 - rotate: false - xy: 341, 377 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -power-node - rotate: false - xy: 341, 411 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -power-node-icon-editor - rotate: false - xy: 341, 411 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -power-source - rotate: false - xy: 409, 479 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -power-void - rotate: false - xy: 35, 71 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -power-void-icon-editor - rotate: false - xy: 35, 71 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -rtg-generator-top - rotate: false - xy: 443, 445 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -solar-panel - rotate: false - xy: 409, 343 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -solar-panel-icon-editor - rotate: false - xy: 409, 343 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -incinerator - rotate: false - xy: 137, 479 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -incinerator-icon-editor - rotate: false - xy: 137, 479 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-source - rotate: false - xy: 1, 241 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-source-icon-editor - rotate: false - xy: 1, 241 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-void - rotate: false - xy: 171, 411 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-void-icon-editor - rotate: false - xy: 171, 411 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -liquid-source - rotate: false - xy: 171, 343 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -liquid-source-icon-editor - rotate: false - xy: 171, 343 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -melter - rotate: false - xy: 69, 207 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -melter-icon-editor - rotate: false - xy: 69, 207 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -pulverizer - rotate: false - xy: 375, 411 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -pulverizer-rotator - rotate: false - xy: 1, 3 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -unloader - rotate: false - xy: 613, 445 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -unloader-icon-editor - rotate: false - xy: 613, 445 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -scorch-heat - rotate: false - xy: 171, 139 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -repair-point-base - rotate: false - xy: 103, 105 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -phase-wall - rotate: false - xy: 137, 207 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -phase-wall-icon-editor - rotate: false - xy: 137, 207 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -scrap-wall1 - rotate: false - xy: 273, 241 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -scrap-wall-icon-editor - rotate: false - xy: 273, 241 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -scrap-wall2 - rotate: false - xy: 307, 275 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -scrap-wall3 - rotate: false - xy: 341, 309 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -scrap-wall4 - rotate: false - xy: 375, 343 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -scrap-wall5 - rotate: false - xy: 375, 343 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -surge-wall - rotate: false - xy: 307, 207 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -surge-wall-icon-editor - rotate: false - xy: 307, 207 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -thorium-wall - rotate: false - xy: 579, 479 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -thorium-wall-icon-editor - rotate: false - xy: 579, 479 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium-wall - rotate: false - xy: 443, 275 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium-wall-icon-editor - rotate: false - xy: 443, 275 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -hail-icon-editor - rotate: false - xy: 69, 445 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -icerocks-icon-editor - rotate: false - xy: 1, 343 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -liquid-router-icon-editor - rotate: false - xy: 1, 173 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -pebbles-icon-editor - rotate: false - xy: 205, 309 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -power-source-icon-editor - rotate: false - xy: 1, 37 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -pulse-conduit-icon-editor - rotate: false - xy: 69, 105 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -pulverizer-icon-editor - rotate: false - xy: 409, 445 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -repair-point-icon-editor - rotate: false - xy: 137, 139 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -rocks-icon-editor - rotate: false - xy: 307, 309 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -saltrocks-icon-editor - rotate: false - xy: 477, 479 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -sandrocks-icon-editor - rotate: false - xy: 69, 37 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -scorch-icon-editor - rotate: false - xy: 205, 173 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -shale-boulder-icon-editor - rotate: false - xy: 103, 37 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -shalerocks-icon-editor - rotate: false - xy: 137, 71 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -shock-mine-icon-editor - rotate: false - xy: 205, 139 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -shrubs-icon-editor - rotate: false - xy: 273, 207 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -snowrocks-icon-editor - rotate: false - xy: 375, 309 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -spawn-icon-editor - rotate: false - xy: 511, 445 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -sporerocks-icon-editor - rotate: false - xy: 239, 139 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -tendrils-icon-editor - rotate: false - xy: 443, 343 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -casing - rotate: false - xy: 661, 259 - size: 8, 16 - orig: 8, 16 - offset: 0, 0 - index: -1 -laser - rotate: false - xy: 1019, 231 - size: 4, 48 - orig: 4, 48 - offset: 0, 0 - index: -1 -minelaser - rotate: false - xy: 619, 23 - size: 4, 48 - orig: 4, 48 - offset: 0, 0 - index: -1 -scale_marker - rotate: false - xy: 549, 131 - size: 4, 4 - orig: 4, 4 - offset: 0, 0 - index: -1 -scorch1 - rotate: false - xy: 443, 173 - size: 28, 100 - orig: 28, 100 - offset: 0, 0 - index: -1 -scorch2 - rotate: false - xy: 473, 173 - size: 28, 100 - orig: 28, 100 - offset: 0, 0 - index: -1 -scorch3 - rotate: false - xy: 503, 207 - size: 28, 100 - orig: 28, 100 - offset: 0, 0 - index: -1 -scorch4 - rotate: false - xy: 533, 241 - size: 28, 100 - orig: 28, 100 - offset: 0, 0 - index: -1 -scorch5 - rotate: false - xy: 563, 275 - size: 28, 100 - orig: 28, 100 - offset: 0, 0 - index: -1 -shot - rotate: false - xy: 239, 173 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -transfer - rotate: false - xy: 625, 23 - size: 4, 48 - orig: 4, 48 - offset: 0, 0 - index: -1 -transfer-arrow - rotate: false - xy: 511, 343 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -alloy-smelter-icon-small - rotate: false - xy: 477, 283 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -arc-icon-small - rotate: false - xy: 239, 11 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -battery-icon-small - rotate: false - xy: 273, 45 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -battery-large-icon-small - rotate: false - xy: 307, 79 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -blast-drill-icon-small - rotate: false - xy: 341, 113 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -blast-mixer-icon-small - rotate: false - xy: 375, 141 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -bridge-conduit-icon-small - rotate: false - xy: 503, 181 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -bridge-conveyor-icon-small - rotate: false - xy: 533, 215 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -char-icon-small - rotate: false - xy: 579, 385 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -cliffs-icon-small - rotate: false - xy: 710, 487 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -coal-centrifuge-icon-small - rotate: false - xy: 710, 461 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -combustion-generator-icon-small - rotate: false - xy: 736, 487 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -conduit-icon-small - rotate: false - xy: 736, 461 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -container-icon-small - rotate: false - xy: 762, 487 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -conveyor-icon-small - rotate: false - xy: 762, 461 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -copper-wall-icon-small - rotate: false - xy: 788, 487 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -copper-wall-large-icon-small - rotate: false - xy: 788, 461 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -core-foundation-icon-small - rotate: false - xy: 814, 487 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -core-nucleus-icon-small - rotate: false - xy: 814, 461 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -core-shard-icon-small - rotate: false - xy: 840, 487 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -craters-icon-small - rotate: false - xy: 840, 461 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -crawler-factory-icon-small - rotate: false - xy: 866, 487 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -cryofluidmixer-icon-small - rotate: false - xy: 866, 461 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -cultivator-icon-small - rotate: false - xy: 892, 487 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -cyclone-icon-small - rotate: false - xy: 892, 461 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -dagger-factory-icon-small - rotate: false - xy: 918, 487 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -dark-metal-icon-small - rotate: false - xy: 918, 461 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -dark-panel-1-icon-small - rotate: false - xy: 944, 487 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -dark-panel-2-icon-small - rotate: false - xy: 944, 461 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -dark-panel-3-icon-small - rotate: false - xy: 970, 487 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -dark-panel-4-icon-small - rotate: false - xy: 970, 461 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -dark-panel-5-icon-small - rotate: false - xy: 996, 487 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -dark-panel-6-icon-small - rotate: false - xy: 996, 461 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -darksand-icon-small - rotate: false - xy: 406, 175 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -darksand-tainted-water-icon-small - rotate: false - xy: 642, 415 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -darksand-water-icon-small - rotate: false - xy: 605, 381 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -dart-mech-pad-icon-small - rotate: false - xy: 710, 435 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -deepwater-icon-small - rotate: false - xy: 736, 435 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -delta-mech-pad-icon-small - rotate: false - xy: 762, 435 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -differential-generator-icon-small - rotate: false - xy: 788, 435 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -distributor-icon-small - rotate: false - xy: 814, 435 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -door-icon-small - rotate: false - xy: 840, 435 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -door-large-icon-small - rotate: false - xy: 866, 435 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -dunerocks-icon-small - rotate: false - xy: 892, 435 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -duo-icon-small - rotate: false - xy: 918, 435 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -force-projector-icon-medium - rotate: false - xy: 1, 445 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -force-projector-icon-small - rotate: false - xy: 944, 435 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -fortress-factory-icon-medium - rotate: false - xy: 35, 479 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -fortress-factory-icon-small - rotate: false - xy: 970, 435 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -fuse-icon-medium - rotate: false - xy: 1, 411 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -fuse-icon-small - rotate: false - xy: 996, 435 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ghoul-factory-icon-medium - rotate: false - xy: 35, 445 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ghoul-factory-icon-small - rotate: false - xy: 631, 381 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -glaive-ship-pad-icon-medium - rotate: false - xy: 69, 479 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -glaive-ship-pad-icon-small - rotate: false - xy: 593, 355 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -graphite-press-icon-medium - rotate: false - xy: 1, 377 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -graphite-press-icon-small - rotate: false - xy: 593, 329 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -grass-icon-small - rotate: false - xy: 619, 355 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -hail - rotate: false - xy: 35, 411 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -hail-icon-full - rotate: false - xy: 103, 479 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -hail-icon-small - rotate: false - xy: 593, 303 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -holostone-icon-small - rotate: false - xy: 619, 329 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -hotrock-icon-small - rotate: false - xy: 593, 277 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ice-icon-small - rotate: false - xy: 619, 303 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ice-snow-icon-small - rotate: false - xy: 619, 277 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -icerocks-icon-small - rotate: false - xy: 645, 355 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ignarock-icon-small - rotate: false - xy: 265, 11 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -impact-reactor-icon-medium - rotate: false - xy: 103, 445 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -impact-reactor-icon-small - rotate: false - xy: 299, 45 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -incinerator-icon-small - rotate: false - xy: 291, 19 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -item-blast-compound-medium - rotate: false - xy: 325, 37 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -item-blast-compound-small - rotate: false - xy: 603, 187 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -item-coal-medium - rotate: false - xy: 317, 11 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -item-coal-small - rotate: false - xy: 603, 169 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -item-copper-medium - rotate: false - xy: 367, 113 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -item-copper-small - rotate: false - xy: 639, 205 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -item-graphite-medium - rotate: false - xy: 359, 87 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -item-graphite-small - rotate: false - xy: 621, 187 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -item-lead-medium - rotate: false - xy: 359, 61 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -item-lead-small - rotate: false - xy: 657, 205 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -item-metaglass-medium - rotate: false - xy: 351, 35 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -item-metaglass-small - rotate: false - xy: 621, 169 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -item-phase-fabric-medium - rotate: false - xy: 343, 9 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -item-phase-fabric-small - rotate: false - xy: 617, 151 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -item-plastanium-medium - rotate: false - xy: 503, 155 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -item-plastanium-small - rotate: false - xy: 639, 187 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -item-pyratite-medium - rotate: false - xy: 533, 189 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -item-pyratite-small - rotate: false - xy: 675, 205 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -item-sand-medium - rotate: false - xy: 529, 163 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -item-sand-small - rotate: false - xy: 617, 133 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -item-scrap-medium - rotate: false - xy: 563, 223 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -item-scrap-small - rotate: false - xy: 639, 169 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -item-silicon-medium - rotate: false - xy: 559, 197 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -item-silicon-small - rotate: false - xy: 635, 151 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -item-source-icon-small - rotate: false - xy: 406, 149 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -item-spore-pod-medium - rotate: false - xy: 432, 147 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -item-spore-pod-small - rotate: false - xy: 657, 187 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -item-surge-alloy-medium - rotate: false - xy: 458, 147 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -item-surge-alloy-small - rotate: false - xy: 693, 205 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -item-thorium-medium - rotate: false - xy: 668, 415 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -item-thorium-small - rotate: false - xy: 635, 133 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -item-titanium-medium - rotate: false - xy: 657, 389 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -item-titanium-small - rotate: false - xy: 657, 169 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -item-void-icon-small - rotate: false - xy: 683, 389 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -javelin-ship-pad-icon-medium - rotate: false - xy: 205, 445 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -javelin-ship-pad-icon-small - rotate: false - xy: 671, 363 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -junction-icon-small - rotate: false - xy: 671, 337 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -kiln-icon-medium - rotate: false - xy: 1, 207 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -kiln-icon-small - rotate: false - xy: 671, 311 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -lancer-icon-medium - rotate: false - xy: 35, 241 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -lancer-icon-small - rotate: false - xy: 671, 285 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -laser-drill-icon-medium - rotate: false - xy: 69, 275 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -laser-drill-icon-small - rotate: false - xy: 697, 363 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -launch-pad-icon-medium - rotate: false - xy: 103, 309 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -launch-pad-icon-small - rotate: false - xy: 697, 337 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -launch-pad-large-icon-medium - rotate: false - xy: 137, 343 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -launch-pad-large-icon-small - rotate: false - xy: 697, 311 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -liquid-junction-icon-small - rotate: false - xy: 697, 285 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -liquid-router-icon-full - rotate: false - xy: 35, 207 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -liquid-router-icon-small - rotate: false - xy: 385, 87 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -liquid-source-icon-small - rotate: false - xy: 385, 61 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -liquid-tank-icon-medium - rotate: false - xy: 205, 377 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -liquid-tank-icon-small - rotate: false - xy: 377, 35 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -magmarock-icon-small - rotate: false - xy: 369, 9 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -mass-driver-icon-medium - rotate: false - xy: 273, 445 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -mass-driver-icon-small - rotate: false - xy: 529, 137 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -mechanical-drill-icon-medium - rotate: false - xy: 307, 479 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -mechanical-drill-icon-small - rotate: false - xy: 559, 171 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -mechanical-pump-icon-small - rotate: false - xy: 555, 145 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -meltdown-icon-medium - rotate: false - xy: 35, 173 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -meltdown-icon-small - rotate: false - xy: 671, 259 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -melter-icon-small - rotate: false - xy: 697, 259 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -mend-projector-icon-medium - rotate: false - xy: 103, 241 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -mend-projector-icon-small - rotate: false - xy: 403, 35 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -mender-icon-small - rotate: false - xy: 395, 9 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -metal-floor-2-icon-small - rotate: false - xy: 555, 119 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -metal-floor-3-icon-small - rotate: false - xy: 421, 9 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -metal-floor-5-icon-small - rotate: false - xy: 393, 115 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -metal-floor-damaged-icon-small - rotate: false - xy: 419, 121 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -metal-floor-icon-small - rotate: false - xy: 445, 121 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -moss-icon-small - rotate: false - xy: 471, 121 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -multi-press-icon-medium - rotate: false - xy: 205, 343 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -multi-press-icon-small - rotate: false - xy: 497, 129 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -oil-extractor-icon-medium - rotate: false - xy: 239, 377 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -oil-extractor-icon-small - rotate: false - xy: 497, 103 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -omega-mech-pad-icon-medium - rotate: false - xy: 273, 411 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -omega-mech-pad-icon-small - rotate: false - xy: 523, 111 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-coal-icon-full - rotate: false - xy: 307, 445 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-icon-medium - rotate: false - xy: 307, 445 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal-icon-small - rotate: false - xy: 523, 85 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-copper-icon-full - rotate: false - xy: 341, 479 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-icon-medium - rotate: false - xy: 341, 479 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper-icon-small - rotate: false - xy: 549, 93 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-lead-icon-full - rotate: false - xy: 1, 105 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-icon-medium - rotate: false - xy: 1, 105 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead-icon-small - rotate: false - xy: 549, 67 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-scrap-icon-full - rotate: false - xy: 35, 139 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-icon-medium - rotate: false - xy: 35, 139 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap-icon-small - rotate: false - xy: 411, 89 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-thorium-icon-full - rotate: false - xy: 69, 173 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-icon-medium - rotate: false - xy: 69, 173 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium-icon-small - rotate: false - xy: 411, 63 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ore-titanium-icon-full - rotate: false - xy: 103, 207 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-icon-medium - rotate: false - xy: 103, 207 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium-icon-small - rotate: false - xy: 437, 95 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -overdrive-projector-icon-medium - rotate: false - xy: 137, 241 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -overdrive-projector-icon-small - rotate: false - xy: 463, 95 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -overflow-gate-icon-small - rotate: false - xy: 437, 69 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -pebbles-icon-small - rotate: false - xy: 463, 69 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -phantom-factory-icon-medium - rotate: false - xy: 239, 343 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -phantom-factory-icon-small - rotate: false - xy: 489, 77 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -phase-conduit-icon-small - rotate: false - xy: 489, 51 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -phase-conveyor-icon-small - rotate: false - xy: 515, 59 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -phase-wall-icon-small - rotate: false - xy: 515, 33 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -phase-wall-large-icon-medium - rotate: false - xy: 171, 241 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -phase-wall-large-icon-small - rotate: false - xy: 541, 41 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -phase-weaver-icon-medium - rotate: false - xy: 205, 275 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -phase-weaver-icon-small - rotate: false - xy: 541, 15 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -pine-icon-medium - rotate: false - xy: 239, 309 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -pine-icon-small - rotate: false - xy: 567, 41 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -plastanium-compressor-icon-medium - rotate: false - xy: 273, 343 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -plastanium-compressor-icon-small - rotate: false - xy: 567, 15 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -pneumatic-drill-icon-medium - rotate: false - xy: 307, 377 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -pneumatic-drill-icon-small - rotate: false - xy: 429, 37 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -power-node-icon-small - rotate: false - xy: 455, 43 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -power-node-large-icon-medium - rotate: false - xy: 375, 445 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -power-node-large-icon-small - rotate: false - xy: 575, 93 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -power-source-icon-small - rotate: false - xy: 575, 67 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -power-void-icon-small - rotate: false - xy: 593, 41 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -pulse-conduit-icon-full - rotate: false - xy: 103, 139 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -pulse-conduit-icon-small - rotate: false - xy: 593, 15 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -pulverizer-icon-full - rotate: false - xy: 443, 479 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -pulverizer-icon-small - rotate: false - xy: 447, 11 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -pyratite-mixer-icon-medium - rotate: false - xy: 35, 37 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -pyratite-mixer-icon-small - rotate: false - xy: 709, 409 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -repair-point - rotate: false - xy: 69, 71 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -repair-point-icon-full - rotate: false - xy: 171, 173 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -repair-point-icon-small - rotate: false - xy: 735, 409 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -revenant-factory-icon-medium - rotate: false - xy: 205, 207 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -revenant-factory-icon-small - rotate: false - xy: 761, 409 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -ripple-icon-medium - rotate: false - xy: 239, 241 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ripple-icon-small - rotate: false - xy: 787, 409 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -rock-icon-medium - rotate: false - xy: 273, 275 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -rock-icon-small - rotate: false - xy: 813, 409 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -rocks-icon-small - rotate: false - xy: 839, 409 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -rotary-pump-icon-medium - rotate: false - xy: 341, 343 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -rotary-pump-icon-small - rotate: false - xy: 865, 409 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -router-icon-small - rotate: false - xy: 891, 409 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -rtg-generator-icon-medium - rotate: false - xy: 409, 411 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -rtg-generator-icon-small - rotate: false - xy: 917, 409 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -salt-icon-small - rotate: false - xy: 943, 409 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -saltrocks-icon-small - rotate: false - xy: 969, 409 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -salvo-icon-medium - rotate: false - xy: 35, 3 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -salvo-icon-small - rotate: false - xy: 995, 409 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -sand-icon-small - rotate: false - xy: 723, 383 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -sand-water-icon-small - rotate: false - xy: 723, 357 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -sandrocks-icon-small - rotate: false - xy: 749, 383 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -scatter-icon-medium - rotate: false - xy: 103, 71 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -scatter-icon-small - rotate: false - xy: 723, 331 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -scorch - rotate: false - xy: 137, 105 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -scorch-icon-full - rotate: false - xy: 239, 207 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -scorch-icon-small - rotate: false - xy: 749, 357 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -scrap-wall-gigantic-icon-medium - rotate: false - xy: 409, 377 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -scrap-wall-gigantic-icon-small - rotate: false - xy: 775, 383 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -scrap-wall-huge-icon-medium - rotate: false - xy: 443, 411 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -scrap-wall-huge-icon-small - rotate: false - xy: 723, 305 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -scrap-wall-icon-small - rotate: false - xy: 749, 331 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -scrap-wall-large-icon-medium - rotate: false - xy: 477, 445 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -scrap-wall-large-icon-small - rotate: false - xy: 775, 357 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -separator-icon-medium - rotate: false - xy: 69, 3 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -separator-icon-small - rotate: false - xy: 749, 305 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -shale-boulder-icon-small - rotate: false - xy: 775, 331 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -shale-icon-small - rotate: false - xy: 801, 341 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -shalerocks-icon-small - rotate: false - xy: 827, 383 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -shock-mine-icon-small - rotate: false - xy: 749, 279 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -shrubs-icon-small - rotate: false - xy: 775, 305 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -silicon-smelter-icon-medium - rotate: false - xy: 307, 241 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -silicon-smelter-icon-small - rotate: false - xy: 801, 315 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -snow-icon-small - rotate: false - xy: 827, 357 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -snowrock-icon-medium - rotate: false - xy: 341, 275 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -snowrock-icon-small - rotate: false - xy: 853, 383 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -snowrocks-icon-small - rotate: false - xy: 775, 279 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -solar-panel-icon-small - rotate: false - xy: 801, 289 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -solar-panel-large-icon-medium - rotate: false - xy: 443, 377 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -solar-panel-large-icon-small - rotate: false - xy: 827, 331 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -sorter-icon-small - rotate: false - xy: 853, 357 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -spawn-icon-small - rotate: false - xy: 879, 383 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -spectre-icon-medium - rotate: false - xy: 545, 479 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -spectre-icon-small - rotate: false - xy: 827, 305 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -spirit-factory-icon-medium - rotate: false - xy: 103, 3 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -spirit-factory-icon-small - rotate: false - xy: 853, 331 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -spore-cluster-icon-medium - rotate: false - xy: 137, 37 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -spore-cluster-icon-small - rotate: false - xy: 879, 357 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -spore-moss-icon-small - rotate: false - xy: 905, 383 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -spore-pine-icon-medium - rotate: false - xy: 171, 71 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -spore-pine-icon-small - rotate: false - xy: 853, 305 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -spore-press-icon-medium - rotate: false - xy: 205, 105 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -spore-press-icon-small - rotate: false - xy: 879, 331 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -sporerocks-icon-small - rotate: false - xy: 905, 357 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -stone-icon-small - rotate: false - xy: 931, 383 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -surge-tower-icon-medium - rotate: false - xy: 273, 173 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -surge-tower-icon-small - rotate: false - xy: 879, 305 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -surge-wall-icon-small - rotate: false - xy: 905, 331 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -surge-wall-large-icon-medium - rotate: false - xy: 341, 241 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -surge-wall-large-icon-small - rotate: false - xy: 931, 357 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -swarmer-icon-medium - rotate: false - xy: 375, 275 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -swarmer-icon-small - rotate: false - xy: 957, 383 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -tainted-water-icon-small - rotate: false - xy: 905, 305 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -tar-icon-small - rotate: false - xy: 931, 331 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -tau-mech-pad-icon-medium - rotate: false - xy: 409, 309 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -tau-mech-pad-icon-small - rotate: false - xy: 957, 357 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -tendrils-icon-small - rotate: false - xy: 983, 383 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -thermal-generator-icon-medium - rotate: false - xy: 477, 377 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -thermal-generator-icon-small - rotate: false - xy: 931, 305 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -thermal-pump-icon-medium - rotate: false - xy: 511, 411 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -thermal-pump-icon-small - rotate: false - xy: 957, 331 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -thorium-reactor-icon-medium - rotate: false - xy: 545, 445 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -thorium-reactor-icon-small - rotate: false - xy: 983, 357 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -thorium-wall-icon-small - rotate: false - xy: 957, 305 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -thorium-wall-large-icon-medium - rotate: false - xy: 137, 3 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -thorium-wall-large-icon-small - rotate: false - xy: 983, 331 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -thruster-icon-medium - rotate: false - xy: 171, 37 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -thruster-icon-small - rotate: false - xy: 983, 305 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -titan-factory-icon-medium - rotate: false - xy: 205, 71 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titan-factory-icon-small - rotate: false - xy: 827, 279 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -titanium-conveyor-icon-small - rotate: false - xy: 853, 279 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -titanium-wall-icon-small - rotate: false - xy: 879, 279 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -titanium-wall-large-icon-medium - rotate: false - xy: 477, 309 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium-wall-large-icon-small - rotate: false - xy: 905, 279 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -trident-ship-pad-icon-medium - rotate: false - xy: 545, 377 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -trident-ship-pad-icon-small - rotate: false - xy: 931, 279 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -turbine-generator-icon-medium - rotate: false - xy: 579, 411 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -turbine-generator-icon-small - rotate: false - xy: 957, 279 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -unloader-icon-small - rotate: false - xy: 983, 279 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -vault-icon-medium - rotate: false - xy: 647, 479 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -vault-icon-small - rotate: false - xy: 801, 263 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -water-extractor-icon-medium - rotate: false - xy: 205, 3 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -water-extractor-icon-small - rotate: false - xy: 827, 253 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -water-icon-small - rotate: false - xy: 853, 253 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -wave-icon-medium - rotate: false - xy: 239, 37 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -wave-icon-small - rotate: false - xy: 879, 253 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -white-tree-dead-icon-medium - rotate: false - xy: 273, 71 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -white-tree-dead-icon-small - rotate: false - xy: 905, 253 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -white-tree-icon-medium - rotate: false - xy: 307, 105 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -white-tree-icon-small - rotate: false - xy: 931, 253 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -wraith-factory-icon-medium - rotate: false - xy: 341, 139 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -wraith-factory-icon-small - rotate: false - xy: 957, 253 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -item-biomatter - rotate: false - xy: 1, 309 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-blast-compound - rotate: false - xy: 35, 343 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-coal - rotate: false - xy: 69, 377 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-copper - rotate: false - xy: 103, 411 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-graphite - rotate: false - xy: 137, 445 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-lead - rotate: false - xy: 171, 479 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-metaglass - rotate: false - xy: 1, 275 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-phase-fabric - rotate: false - xy: 35, 309 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-plastanium - rotate: false - xy: 69, 343 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-pyratite - rotate: false - xy: 103, 377 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-sand - rotate: false - xy: 137, 411 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-scrap - rotate: false - xy: 171, 445 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-silicon - rotate: false - xy: 205, 479 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-spore-pod - rotate: false - xy: 35, 275 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-surge-alloy - rotate: false - xy: 69, 309 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-thorium - rotate: false - xy: 103, 343 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -item-titanium - rotate: false - xy: 137, 377 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -liquid-cryofluid - rotate: false - xy: 171, 377 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -liquid-oil - rotate: false - xy: 239, 445 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -liquid-slag - rotate: false - xy: 137, 309 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -liquid-water - rotate: false - xy: 239, 411 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -blank - rotate: false - xy: 406, 204 - size: 1, 1 - orig: 1, 1 - offset: 0, 0 - index: -1 -clear - rotate: false - xy: 406, 201 - size: 1, 1 - orig: 1, 1 - offset: 0, 0 - index: -1 -clear-editor - rotate: false - xy: 406, 201 - size: 1, 1 - orig: 1, 1 - offset: 0, 0 - index: -1 -bar - rotate: false - xy: 647, 441 - size: 27, 36 - split: 9, 9, 9, 9 - orig: 27, 36 - offset: 0, 0 - index: -1 -bar-top - rotate: false - xy: 613, 407 - size: 27, 36 - split: 9, 10, 9, 10 - orig: 27, 36 - offset: 0, 0 - index: -1 -button-select - rotate: false - xy: 563, 249 - size: 24, 24 - split: 4, 4, 4, 4 - orig: 24, 24 - offset: 0, 0 - index: -1 -clear - rotate: false - xy: 709, 397 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -editor-clear - rotate: false - xy: 709, 397 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -cursor - rotate: false - xy: 523, 149 - size: 4, 4 - orig: 4, 4 - offset: 0, 0 - index: -1 -empty-sector - rotate: false - xy: 1, 479 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -icon-crafting - rotate: false - xy: 983, 243 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-defense - rotate: false - xy: 1001, 261 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-distribution - rotate: false - xy: 585, 205 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-effect - rotate: false - xy: 585, 187 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-liquid - rotate: false - xy: 625, 241 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-power - rotate: false - xy: 759, 243 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-production - rotate: false - xy: 777, 243 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-turret - rotate: false - xy: 643, 223 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-units - rotate: false - xy: 679, 223 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-upgrade - rotate: false - xy: 603, 205 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -controller-cursor - rotate: false - xy: 545, 359 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-about - rotate: false - xy: 785, 263 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-add - rotate: false - xy: 545, 343 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-admin - rotate: false - xy: 589, 223 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-admin-small - rotate: false - xy: 317, 37 - size: 6, 6 - orig: 6, 6 - offset: 0, 0 - index: -1 -icon-areaDelete - rotate: false - xy: 511, 311 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-arrow - rotate: false - xy: 291, 1 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-arrow-16 - rotate: false - xy: 291, 1 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-arrow-down - rotate: false - xy: 813, 251 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-arrow-left - rotate: false - xy: 527, 21 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-arrow-right - rotate: false - xy: 581, 121 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-arrow-up - rotate: false - xy: 593, 121 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-back - rotate: false - xy: 484, 155 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-ban - rotate: false - xy: 1009, 393 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-break - rotate: false - xy: 983, 261 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-cancel - rotate: false - xy: 749, 261 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-cancel-2 - rotate: false - xy: 645, 329 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -icon-chat - rotate: false - xy: 605, 121 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-check - rotate: false - xy: 767, 261 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-check-2 - rotate: false - xy: 645, 303 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -icon-copy - rotate: false - xy: 723, 250 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-cursor - rotate: false - xy: 617, 121 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-database - rotate: false - xy: 1009, 377 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-database-small - rotate: false - xy: 629, 121 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-dev-builds - rotate: false - xy: 1009, 361 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-diagonal - rotate: false - xy: 1001, 243 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-discord - rotate: false - xy: 1009, 345 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-donate - rotate: false - xy: 1009, 329 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-dots - rotate: false - xy: 1009, 313 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-editor - rotate: false - xy: 1009, 297 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-egg - rotate: false - xy: 1009, 281 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-elevation - rotate: false - xy: 585, 169 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-eraser - rotate: false - xy: 581, 151 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-exit - rotate: false - xy: 653, 153 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-file - rotate: false - xy: 581, 133 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-file-image - rotate: false - xy: 589, 257 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-file-text - rotate: false - xy: 675, 189 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-fill - rotate: false - xy: 589, 239 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-floppy - rotate: false - xy: 653, 137 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-floppy-16 - rotate: false - xy: 607, 259 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-folder - rotate: false - xy: 675, 173 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-folder-parent - rotate: false - xy: 691, 189 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-github - rotate: false - xy: 691, 173 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-google-play - rotate: false - xy: 715, 234 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-grid - rotate: false - xy: 607, 241 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-hold - rotate: false - xy: 641, 121 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-holdDelete - rotate: false - xy: 653, 125 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-home - rotate: false - xy: 715, 218 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-host - rotate: false - xy: 711, 202 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-info - rotate: false - xy: 707, 186 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-itch.io - rotate: false - xy: 707, 170 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-item - rotate: false - xy: 665, 125 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-items-none - rotate: false - xy: 239, 1 - size: 8, 8 - orig: 8, 8 - offset: 0, 0 - index: -1 -icon-line - rotate: false - xy: 625, 259 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-link - rotate: false - xy: 669, 153 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-liquid-small - rotate: false - xy: 601, 109 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-load - rotate: false - xy: 669, 137 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-load-image - rotate: false - xy: 643, 259 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-load-map - rotate: false - xy: 643, 241 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-loading - rotate: false - xy: 661, 241 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-locked - rotate: false - xy: 679, 241 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-logic - rotate: false - xy: 601, 97 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-map - rotate: false - xy: 685, 157 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-menu - rotate: false - xy: 613, 109 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-menu-large - rotate: false - xy: 697, 241 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-missing - rotate: false - xy: 601, 85 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-mission-background - rotate: false - xy: 511, 323 - size: 18, 18 - orig: 18, 18 - offset: 0, 0 - index: -1 -icon-mission-battle - rotate: false - xy: 625, 109 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-mission-defense - rotate: false - xy: 613, 97 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-mission-done - rotate: false - xy: 601, 73 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-none - rotate: false - xy: 637, 109 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-paste - rotate: false - xy: 599, 151 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-pause - rotate: false - xy: 625, 97 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-pencil - rotate: false - xy: 599, 133 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-pencil-small - rotate: false - xy: 685, 141 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-pick - rotate: false - xy: 741, 243 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-play - rotate: false - xy: 613, 85 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-play-2 - rotate: false - xy: 701, 154 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-play-custom - rotate: false - xy: 701, 138 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-players - rotate: false - xy: 637, 97 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-power-requirement - rotate: false - xy: 35, 377 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -icon-power-small - rotate: false - xy: 625, 85 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-quit - rotate: false - xy: 685, 125 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-redo - rotate: false - xy: 795, 245 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-refresh - rotate: false - xy: 701, 122 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-rename - rotate: false - xy: 731, 227 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-resize - rotate: false - xy: 473, 25 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-rotate - rotate: false - xy: 747, 227 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-rotate-arrow - rotate: false - xy: 763, 227 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-rotate-left - rotate: false - xy: 779, 227 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-rotate-right - rotate: false - xy: 795, 229 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-save - rotate: false - xy: 731, 211 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-save-image - rotate: false - xy: 473, 7 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-save-map - rotate: false - xy: 491, 33 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-settings - rotate: false - xy: 613, 73 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-spray - rotate: false - xy: 491, 15 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-terrain - rotate: false - xy: 509, 15 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-tools - rotate: false - xy: 747, 211 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-touch - rotate: false - xy: 637, 85 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-touchDelete - rotate: false - xy: 625, 73 - size: 10, 10 - orig: 10, 10 - offset: 0, 0 - index: -1 -icon-trash - rotate: false - xy: 763, 211 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-trash-16 - rotate: false - xy: 607, 223 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-tree - rotate: false - xy: 625, 223 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-tree-locked - rotate: false - xy: 69, 411 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -icon-trello - rotate: false - xy: 779, 211 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-tutorial - rotate: false - xy: 795, 213 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-undo - rotate: false - xy: 661, 223 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-unlocked - rotate: false - xy: 697, 223 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-unlocks - rotate: false - xy: 717, 154 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-wiki - rotate: false - xy: 717, 138 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -icon-zone - rotate: false - xy: 645, 277 - size: 24, 24 - orig: 24, 24 - offset: 0, 0 - index: -1 -icon-zoom - rotate: false - xy: 621, 205 - size: 16, 16 - orig: 16, 16 - offset: 0, 0 - index: -1 -icon-zoom-small - rotate: false - xy: 717, 122 - size: 14, 14 - orig: 14, 14 - offset: 0, 0 - index: -1 -inventory - rotate: false - xy: 333, 63 - size: 24, 40 - split: 10, 10, 10, 14 - orig: 24, 40 - offset: 0, 0 - index: -1 -scroll - rotate: false - xy: 723, 268 - size: 24, 35 - split: 10, 10, 6, 5 - orig: 24, 35 - offset: 0, 0 - index: -1 -scroll-knob-vertical-black - rotate: false - xy: 801, 367 - size: 24, 40 - split: 10, 10, 6, 10 - orig: 24, 40 - offset: 0, 0 - index: -1 -sector-select - rotate: false - xy: 511, 479 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -selection - rotate: false - xy: 440, 238 - size: 1, 1 - orig: 1, 1 - offset: 0, 0 - index: -1 -slider - rotate: false - xy: 1022, 503 - size: 1, 8 - orig: 1, 8 - offset: 0, 0 - index: -1 -slider-knob - rotate: false - xy: 375, 167 - size: 29, 38 - orig: 29, 38 - offset: 0, 0 - index: -1 -slider-knob-down - rotate: false - xy: 409, 201 - size: 29, 38 - orig: 29, 38 - offset: 0, 0 - index: -1 -slider-knob-over - rotate: false - xy: 409, 201 - size: 29, 38 - orig: 29, 38 - offset: 0, 0 - index: -1 -slider-vertical - rotate: false - xy: 675, 170 - size: 8, 1 - orig: 8, 1 - offset: 0, 0 - index: -1 -white - rotate: false - xy: 676, 474 - size: 3, 3 - orig: 3, 3 - offset: 0, 0 - index: -1 -window-empty - rotate: false - xy: 681, 450 - size: 27, 61 - split: 8, 8, 44, 11 - orig: 27, 61 - offset: 0, 0 - index: -1 - -sprites_fallback6.png -size: 1024,1024 -format: RGBA8888 -filter: Nearest,Nearest -repeat: none -char1 - rotate: false - xy: 781, 789 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -char2 - rotate: false - xy: 879, 887 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -char3 - rotate: false - xy: 585, 495 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -cliffs1 - rotate: false - xy: 781, 755 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -coal1 - rotate: false - xy: 879, 853 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -coal2 - rotate: false - xy: 585, 461 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -coal3 - rotate: false - xy: 265, 47 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -copper1 - rotate: false - xy: 265, 13 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -copper2 - rotate: false - xy: 295, 341 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -copper3 - rotate: false - xy: 295, 307 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -craters1 - rotate: false - xy: 295, 273 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -craters2 - rotate: false - xy: 295, 239 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -craters3 - rotate: false - xy: 295, 205 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -craters4 - rotate: false - xy: 295, 171 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -craters5 - rotate: false - xy: 295, 137 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -craters6 - rotate: false - xy: 295, 103 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -dark-metal-large - rotate: false - xy: 1, 15 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -dark-metal1 - rotate: false - xy: 329, 347 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -dark-metal2 - rotate: false - xy: 329, 313 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -dark-panel-1 - rotate: false - xy: 363, 347 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -dark-panel-1-edge - rotate: false - xy: 323, 921 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -dark-panel-2 - rotate: false - xy: 329, 279 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -dark-panel-2-edge - rotate: false - xy: 1, 277 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -dark-panel-3 - rotate: false - xy: 363, 313 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -dark-panel-3-edge - rotate: false - xy: 323, 823 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -dark-panel-4 - rotate: false - xy: 397, 347 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -dark-panel-4-edge - rotate: false - xy: 421, 921 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -dark-panel-5 - rotate: false - xy: 329, 245 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -dark-panel-5-edge - rotate: false - xy: 1, 179 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -dark-panel-6 - rotate: false - xy: 363, 279 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -dark-panel-6-edge - rotate: false - xy: 99, 277 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -darksand-edge - rotate: false - xy: 323, 725 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -darksand-tainted-water - rotate: false - xy: 363, 245 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -darksand-tainted-water-edge - rotate: false - xy: 421, 823 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -darksand-water - rotate: false - xy: 397, 279 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -darksand-water-edge - rotate: false - xy: 519, 921 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -darksand1 - rotate: false - xy: 397, 313 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -darksand2 - rotate: false - xy: 431, 347 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -darksand3 - rotate: false - xy: 329, 211 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -deepwater - rotate: false - xy: 431, 313 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -deepwater-edge - rotate: false - xy: 1, 81 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -dunerocks-large - rotate: false - xy: 617, 659 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -dunerocks1 - rotate: false - xy: 465, 347 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -dunerocks2 - rotate: false - xy: 329, 177 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -edge - rotate: false - xy: 363, 211 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -edge-stencil - rotate: false - xy: 99, 179 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -edgier - rotate: false - xy: 397, 245 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -grass-edge - rotate: false - xy: 197, 277 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -grass1 - rotate: false - xy: 431, 279 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -grass2 - rotate: false - xy: 465, 313 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -grass3 - rotate: false - xy: 329, 143 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -holostone-edge - rotate: false - xy: 323, 627 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -holostone1 - rotate: false - xy: 363, 177 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -holostone2 - rotate: false - xy: 397, 211 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -holostone3 - rotate: false - xy: 431, 245 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -hotrock1 - rotate: false - xy: 465, 279 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -hotrock2 - rotate: false - xy: 329, 109 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -hotrock3 - rotate: false - xy: 363, 143 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ice-edge - rotate: false - xy: 421, 725 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -ice-snow-edge - rotate: false - xy: 519, 823 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -ice-snow1 - rotate: false - xy: 363, 109 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ice-snow2 - rotate: false - xy: 397, 143 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ice-snow3 - rotate: false - xy: 431, 177 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ice1 - rotate: false - xy: 397, 177 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ice2 - rotate: false - xy: 431, 211 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ice3 - rotate: false - xy: 465, 245 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -icerocks-large - rotate: false - xy: 715, 757 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -icerocks1 - rotate: false - xy: 465, 211 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -icerocks2 - rotate: false - xy: 397, 109 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ignarock-edge - rotate: false - xy: 617, 921 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -ignarock1 - rotate: false - xy: 431, 143 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ignarock2 - rotate: false - xy: 465, 177 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ignarock3 - rotate: false - xy: 431, 109 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -lead1 - rotate: false - xy: 465, 143 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -lead2 - rotate: false - xy: 465, 109 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -lead3 - rotate: false - xy: 977, 943 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -magmarock1 - rotate: false - xy: 499, 347 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -magmarock2 - rotate: false - xy: 499, 313 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -magmarock3 - rotate: false - xy: 499, 279 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -metal-floor - rotate: false - xy: 499, 245 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -metal-floor-2 - rotate: false - xy: 499, 211 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -metal-floor-2-edge - rotate: false - xy: 99, 81 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -metal-floor-3 - rotate: false - xy: 499, 177 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -metal-floor-3-edge - rotate: false - xy: 197, 179 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -metal-floor-5 - rotate: false - xy: 499, 143 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -metal-floor-5-edge - rotate: false - xy: 323, 529 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -metal-floor-damaged-edge - rotate: false - xy: 421, 627 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -metal-floor-damaged1 - rotate: false - xy: 499, 109 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -metal-floor-damaged2 - rotate: false - xy: 619, 509 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -metal-floor-damaged3 - rotate: false - xy: 619, 475 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -metal-floor-edge - rotate: false - xy: 519, 725 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -moss-edge - rotate: false - xy: 617, 823 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -moss1 - rotate: false - xy: 667, 557 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -moss2 - rotate: false - xy: 701, 557 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -moss3 - rotate: false - xy: 653, 509 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal1 - rotate: false - xy: 653, 475 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal2 - rotate: false - xy: 687, 523 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-coal3 - rotate: false - xy: 687, 489 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper1 - rotate: false - xy: 619, 441 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper2 - rotate: false - xy: 653, 441 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-copper3 - rotate: false - xy: 687, 455 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead1 - rotate: false - xy: 721, 523 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead2 - rotate: false - xy: 721, 489 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-lead3 - rotate: false - xy: 721, 455 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap1 - rotate: false - xy: 687, 421 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap2 - rotate: false - xy: 721, 421 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-scrap3 - rotate: false - xy: 299, 69 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium1 - rotate: false - xy: 299, 35 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium2 - rotate: false - xy: 333, 75 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-thorium3 - rotate: false - xy: 333, 41 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium1 - rotate: false - xy: 367, 75 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium2 - rotate: false - xy: 367, 41 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -ore-titanium3 - rotate: false - xy: 401, 75 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -pebbles1 - rotate: false - xy: 401, 41 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -pebbles2 - rotate: false - xy: 435, 75 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -pebbles3 - rotate: false - xy: 435, 41 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -pine - rotate: false - xy: 323, 381 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -rock1 - rotate: false - xy: 617, 543 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -rock2 - rotate: false - xy: 373, 381 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -rocks-large - rotate: false - xy: 813, 855 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -rocks1 - rotate: false - xy: 469, 75 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -rocks2 - rotate: false - xy: 469, 41 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -salt - rotate: false - xy: 503, 75 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -salt-edge - rotate: false - xy: 715, 921 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -saltrocks-large - rotate: false - xy: 911, 953 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -saltrocks1 - rotate: false - xy: 503, 41 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -saltrocks2 - rotate: false - xy: 299, 1 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -sand-edge - rotate: false - xy: 197, 81 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -sand-water - rotate: false - xy: 435, 7 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -sand-water-edge - rotate: false - xy: 323, 431 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -sand1 - rotate: false - xy: 333, 7 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -sand2 - rotate: false - xy: 367, 7 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -sand3 - rotate: false - xy: 401, 7 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -sandrocks-large - rotate: false - xy: 519, 463 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -sandrocks1 - rotate: false - xy: 469, 7 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -sandrocks2 - rotate: false - xy: 503, 7 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -scrap1 - rotate: false - xy: 725, 641 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -scrap2 - rotate: false - xy: 725, 607 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -scrap3 - rotate: false - xy: 735, 573 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -shale-boulder1 - rotate: false - xy: 849, 819 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -shale-boulder2 - rotate: false - xy: 849, 785 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -shale-edge - rotate: false - xy: 421, 529 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -shale1 - rotate: false - xy: 815, 821 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -shale2 - rotate: false - xy: 815, 787 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -shale3 - rotate: false - xy: 815, 753 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -shalerocks-large - rotate: false - xy: 67, 15 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -shalerocks1 - rotate: false - xy: 849, 751 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -shalerocks2 - rotate: false - xy: 883, 819 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -shrubs-large - rotate: false - xy: 617, 593 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -shrubs1 - rotate: false - xy: 883, 785 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -shrubs2 - rotate: false - xy: 883, 751 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -snow-edge - rotate: false - xy: 519, 627 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -snow1 - rotate: false - xy: 523, 429 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -snow2 - rotate: false - xy: 523, 395 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -snow3 - rotate: false - xy: 533, 361 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -snowrock1 - rotate: false - xy: 423, 381 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -snowrock2 - rotate: false - xy: 473, 381 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -snowrocks-large - rotate: false - xy: 133, 15 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -snowrocks1 - rotate: false - xy: 533, 327 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -snowrocks2 - rotate: false - xy: 533, 293 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -spawn - rotate: false - xy: 533, 259 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -spore-cluster1 - rotate: false - xy: 977, 977 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -spore-cluster2 - rotate: false - xy: 683, 633 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -spore-cluster3 - rotate: false - xy: 683, 591 - size: 40, 40 - orig: 40, 40 - offset: 0, 0 - index: -1 -spore-moss-edge - rotate: false - xy: 617, 725 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -spore-moss1 - rotate: false - xy: 533, 225 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -spore-moss2 - rotate: false - xy: 533, 191 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -spore-moss3 - rotate: false - xy: 533, 157 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -spore-pine - rotate: false - xy: 683, 675 - size: 48, 48 - orig: 48, 48 - offset: 0, 0 - index: -1 -sporerocks-large - rotate: false - xy: 199, 15 - size: 64, 64 - orig: 64, 64 - offset: 0, 0 - index: -1 -sporerocks1 - rotate: false - xy: 533, 123 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -sporerocks2 - rotate: false - xy: 537, 89 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -stone-edge - rotate: false - xy: 715, 823 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -stone1 - rotate: false - xy: 537, 55 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -stone2 - rotate: false - xy: 537, 21 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -stone3 - rotate: false - xy: 557, 427 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -tainted-water - rotate: false - xy: 733, 723 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -tainted-water-edge - rotate: false - xy: 813, 921 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -tar - rotate: false - xy: 733, 689 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -tar-edge - rotate: false - xy: 421, 431 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -tendrils1 - rotate: false - xy: 767, 721 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -tendrils2 - rotate: false - xy: 767, 687 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -tendrils3 - rotate: false - xy: 801, 719 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -thorium1 - rotate: false - xy: 801, 685 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -thorium2 - rotate: false - xy: 835, 717 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -thorium3 - rotate: false - xy: 869, 717 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium1 - rotate: false - xy: 835, 683 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium2 - rotate: false - xy: 869, 683 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -titanium3 - rotate: false - xy: 759, 653 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -water - rotate: false - xy: 759, 619 - size: 32, 32 - orig: 32, 32 - offset: 0, 0 - index: -1 -water-edge - rotate: false - xy: 519, 529 - size: 96, 96 - orig: 96, 96 - offset: 0, 0 - index: -1 -white-tree - rotate: false - xy: 1, 697 - size: 320, 320 - orig: 320, 320 - offset: 0, 0 - index: -1 -white-tree-dead - rotate: false - xy: 1, 375 - size: 320, 320 - orig: 320, 320 - offset: 0, 0 - index: -1 diff --git a/core/assets/sprites/sprites_fallback.png b/core/assets/sprites/sprites_fallback.png deleted file mode 100644 index bb1ac34103..0000000000 Binary files a/core/assets/sprites/sprites_fallback.png and /dev/null differ diff --git a/core/assets/sprites/sprites_fallback2.png b/core/assets/sprites/sprites_fallback2.png deleted file mode 100644 index 142dfcffe0..0000000000 Binary files a/core/assets/sprites/sprites_fallback2.png and /dev/null differ diff --git a/core/assets/sprites/sprites_fallback3.png b/core/assets/sprites/sprites_fallback3.png deleted file mode 100644 index b54e392254..0000000000 Binary files a/core/assets/sprites/sprites_fallback3.png and /dev/null differ diff --git a/core/assets/sprites/sprites_fallback4.png b/core/assets/sprites/sprites_fallback4.png deleted file mode 100644 index 94f3c42c50..0000000000 Binary files a/core/assets/sprites/sprites_fallback4.png and /dev/null differ diff --git a/core/assets/sprites/sprites_fallback5.png b/core/assets/sprites/sprites_fallback5.png deleted file mode 100644 index 03046ffb6e..0000000000 Binary files a/core/assets/sprites/sprites_fallback5.png and /dev/null differ diff --git a/core/assets/sprites/sprites_fallback6.png b/core/assets/sprites/sprites_fallback6.png deleted file mode 100644 index 8762b3e5af..0000000000 Binary files a/core/assets/sprites/sprites_fallback6.png and /dev/null differ diff --git a/core/assets/sprites/uiskin.json b/core/assets/sprites/uiskin.json index 3931878115..5c0e25d6e1 100644 --- a/core/assets/sprites/uiskin.json +++ b/core/assets/sprites/uiskin.json @@ -9,15 +9,15 @@ }, TintedDrawable: { dialogDim: { - name: white, + name: whiteui, color: { r: 0, g: 0, b: 0, a: 0.9 } }, guideDim: { - name: white, + name: whiteui, color: { r: 0, g: 0, b: 0, a: 0.3 } }, invis: { - name: white, + name: whiteui, color: { r: 0, g: 0, b: 0, a: 0 } } loadDim: { @@ -25,28 +25,28 @@ color: { r: 0, g: 0, b: 0, a: 0.8 } }, chatfield: { - name: white, + name: whiteui, color: { r: 0, g: 0, b: 0, a: 0.2 } }, dark: { - name: white, + name: whiteui, color: { hex: "#000000ff" } }, none: { - name: white, + name: whiteui, color: { r: 0, g: 0, b: 0, a: 0 } }, - flat: { - name: white, + flat-trans: { + name: whiteui, color: { r: 0.0, g: 0.0, b: 0.0, a: 0.6 } }, - flat-over: { - name: white, - color: { hex: "#ffffff82" } + flat: { + name: whiteui, + color: { r: 0.0, g: 0.0, b: 0.0, a: 1 } }, - flat-down: { - name: white, - color: { hex: "#ffd37fff" } + flat-over: { + name: whiteui, + color: { hex: "#454545ff" } } }, ButtonStyle: { @@ -71,12 +71,12 @@ up: button }, node: { - disabled: content-background-locked, + disabled: button, font: default-font, fontColor: white, disabledFontColor: gray, - up: content-background, - over: content-background-over + up: button-over, + over: button-down }, right: { over: button-right-over, @@ -111,8 +111,8 @@ up: info-banner }, clear-partial: { - down: white, - up: button-select, + down: whiteui, + up: pane, over: flat-down, font: default-font, fontColor: white, @@ -138,6 +138,16 @@ over: flat-over, disabled: flat, disabledFontColor: gray + }, + clear-toggle-menu: { + font: default-font, + fontColor: white, + checked: flat-down, + down: flat-down, + up: clear, + over: flat-over, + disabled: flat, + disabledFontColor: gray } toggle: { font: default-font, @@ -146,7 +156,7 @@ down: button-down, up: button, over: button-over, - disabled: button, + disabled: button-disabled, disabledFontColor: gray } }, @@ -159,8 +169,8 @@ imageUpColor: white }, node: { - up: content-background, - over: content-background-over + up: button-over, + over: button-down }, right: { over: button-right-over, @@ -199,8 +209,8 @@ over: flat-over }, clear-full: { - down: white, - up: button-select, + down: whiteui, + up: pane, over: flat-down }, clear-partial: { @@ -214,6 +224,17 @@ up: flat, over: flat-over }, + clear-trans: { + down: flat-down, + up: flat-trans, + over: flat-over + }, + clear-toggle-trans: { + down: flat-down, + checked: flat-down, + up: flat-trans, + over: flat-over + }, clear-toggle-partial: { down: flat-down, checked: flat-down, @@ -243,6 +264,12 @@ titleFont: default-font, background: window-empty, titleFontColor: accent + }, + fulldialog: { + stageBackground: dark, + titleFont: default-font, + background: window-empty, + titleFontColor: accent } }, KeybindDialogStyle: { diff --git a/core/src/io/anuke/mindustry/Mindustry.java b/core/src/io/anuke/mindustry/Mindustry.java index 195d2153f7..5a58e9b30e 100644 --- a/core/src/io/anuke/mindustry/Mindustry.java +++ b/core/src/io/anuke/mindustry/Mindustry.java @@ -1,6 +1,7 @@ package io.anuke.mindustry; import io.anuke.arc.*; +import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Log; import io.anuke.arc.util.Time; import io.anuke.mindustry.core.*; @@ -10,18 +11,18 @@ import io.anuke.mindustry.io.BundleLoader; import static io.anuke.mindustry.Vars.*; public class Mindustry extends ApplicationCore{ + private long lastTime; @Override 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 : Mathf.clamp(result, 0.0001f, 60f / 10f); }); Time.mark(); Vars.init(); - Log.setUseColors(false); BundleLoader.load(); content.load(); @@ -36,6 +37,27 @@ public class Mindustry extends ApplicationCore{ add(netClient = new NetClient()); } + @Override + public void update(){ + super.update(); + + int targetfps = Core.settings.getInt("fpscap", 120); + + if(targetfps > 0 && targetfps <= 240){ + long target = (1000 * 1000000) / targetfps; //target in nanos + long elapsed = Time.timeSinceNanos(lastTime); + if(elapsed < target){ + try{ + Thread.sleep((target - elapsed) / 1000000, (int)((target - elapsed) % 1000000)); + }catch(InterruptedException ignored){ + //ignore + } + } + } + + lastTime = Time.nanos(); + } + @Override public void init(){ super.init(); @@ -43,26 +65,4 @@ public class Mindustry extends ApplicationCore{ Log.info("Time to load [total]: {0}", Time.elapsed()); Events.fire(new GameLoadEvent()); } - - @Override - public void update(){ - long lastFrameTime = Time.nanos(); - - super.update(); - - int fpsCap = Core.settings.getInt("fpscap", 125); - - if(fpsCap <= 120){ - long target = (1000 * 1000000) / fpsCap; //target in nanos - long elapsed = Time.timeSinceNanos(lastFrameTime); - if(elapsed < target){ - try{ - Thread.sleep((target - elapsed) / 1000000, (int)((target - elapsed) % 1000000)); - }catch(InterruptedException e){ - e.printStackTrace(); - } - } - } - } - } diff --git a/core/src/io/anuke/mindustry/Vars.java b/core/src/io/anuke/mindustry/Vars.java index a84cfefbe4..8d9a4e0c5f 100644 --- a/core/src/io/anuke/mindustry/Vars.java +++ b/core/src/io/anuke/mindustry/Vars.java @@ -37,8 +37,6 @@ public class Vars{ public static final String donationURL = "https://anuke.itch.io/mindustry/purchase"; /** URL for discord invite. */ public static final String discordURL = "https://discord.gg/mindustry"; - /** URL for Github API for releases */ - public static final String releasesURL = "https://api.github.com/repos/Anuken/Mindustry/releases"; /** URL for sending crash reports to */ public static final String crashReportURL = "http://mins.us.to/report"; /** maximum distance between mine and core that supports automatic transferring */ @@ -47,6 +45,8 @@ public class Vars{ public static final Team defaultTeam = Team.blue; /** team of the enemy in waves/sectors */ public static final Team waveTeam = Team.red; + /** whether to enable editing of units in the editor */ + public static final boolean enableUnitEditing = false; /** max chat message length */ public static final int maxTextLength = 150; /** max player name length in bytes */ @@ -55,6 +55,14 @@ public class Vars{ public static final float itemSize = 5f; /** extra padding around the world; units outside this bound will begin to self-destruct. */ public static final float worldBounds = 100f; + /** default size of UI icons.*/ + public static final int iconsize = 48; + /** size of UI icons (small)*/ + public static final int iconsizesmall = 32; + /** size of UI icons (medium)*/ + public static final int iconsizemed = 30; + /** size of UI icons (medium)*/ + public static final int iconsizetiny = 16; /** units outside of this bound will simply die instantly */ public static final float finalWorldBounds = worldBounds + 500; /** ticks spent out of bound until self destruct. */ @@ -84,6 +92,10 @@ public class Vars{ }; /** default server port */ public static final int port = 6567; + /** multicast discovery port.*/ + public static final int multicastPort = 20151; + /** multicast group for discovery.*/ + public static final String multicastGroup = "227.2.7.7"; /** if true, UI is not drawn */ public static boolean disableUI; /** if true, game is set up in mobile mode, even on desktop. used for debugging */ @@ -120,6 +132,7 @@ public class Vars{ public static GameState state; public static GlobalData data; public static EntityCollisions collisions; + public static DefaultWaves defaultWaves; public static Control control; public static Logic logic; @@ -168,6 +181,7 @@ public class Vars{ content.setVerbose(); } + defaultWaves = new DefaultWaves(); collisions = new EntityCollisions(); playerGroup = Entities.addGroup(Player.class).enableMapping(); diff --git a/core/src/io/anuke/mindustry/ai/BlockIndexer.java b/core/src/io/anuke/mindustry/ai/BlockIndexer.java index 61500ae687..71a79a262c 100644 --- a/core/src/io/anuke/mindustry/ai/BlockIndexer.java +++ b/core/src/io/anuke/mindustry/ai/BlockIndexer.java @@ -1,29 +1,26 @@ package io.anuke.mindustry.ai; -import io.anuke.arc.Events; +import io.anuke.arc.*; import io.anuke.arc.collection.*; -import io.anuke.arc.function.Predicate; -import io.anuke.arc.math.Mathf; -import io.anuke.arc.math.geom.Geometry; -import io.anuke.mindustry.content.Blocks; -import io.anuke.mindustry.entities.type.TileEntity; -import io.anuke.mindustry.game.EventType.TileChangeEvent; -import io.anuke.mindustry.game.EventType.WorldLoadEvent; -import io.anuke.mindustry.game.Team; -import io.anuke.mindustry.game.Teams.TeamData; -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.meta.BlockFlag; +import io.anuke.arc.function.*; +import io.anuke.arc.math.*; +import io.anuke.arc.math.geom.*; +import io.anuke.mindustry.content.*; +import io.anuke.mindustry.entities.type.*; +import io.anuke.mindustry.game.EventType.*; +import io.anuke.mindustry.game.*; +import io.anuke.mindustry.game.Teams.*; +import io.anuke.mindustry.type.*; +import io.anuke.mindustry.world.*; +import io.anuke.mindustry.world.meta.*; import static io.anuke.mindustry.Vars.*; /** Class used for indexing special target blocks for AI. */ @SuppressWarnings("unchecked") public class BlockIndexer{ - /** Size of one ore quadrant. */ - private final static int oreQuadrantSize = 20; - /** Size of one structure quadrant. */ - private final static int structQuadrantSize = 12; + /** Size of one quadrant. */ + private final static int quadrantSize = 16; /** Set of all ores that are being scanned. */ private final ObjectSet scanOres = ObjectSet.with(Item.getAllOres().toArray(Item.class)); @@ -75,7 +72,7 @@ public class BlockIndexer{ //create bitset for each team type that contains each quadrant structQuadrants = new GridBits[Team.all.length]; for(int i = 0; i < Team.all.length; i++){ - structQuadrants[i] = new GridBits(Mathf.ceil(world.width() / (float)structQuadrantSize), Mathf.ceil(world.height() / (float)structQuadrantSize)); + structQuadrants[i] = new GridBits(Mathf.ceil(world.width() / (float)quadrantSize), Mathf.ceil(world.height() / (float)quadrantSize)); } for(int x = 0; x < world.width(); x++){ @@ -94,7 +91,7 @@ public class BlockIndexer{ for(int x = 0; x < quadWidth(); x++){ for(int y = 0; y < quadHeight(); y++){ - updateQuadrant(world.tile(x * structQuadrantSize, y * structQuadrantSize)); + updateQuadrant(world.tile(x * quadrantSize, y * quadrantSize)); } } @@ -164,13 +161,13 @@ public class BlockIndexer{ TileEntity closest = null; float dst = 0; - for(int rx = Math.max((int)((x - range) / tilesize / structQuadrantSize), 0); rx <= (int)((x + range) / tilesize / structQuadrantSize) && rx < quadWidth(); rx++){ - for(int ry = Math.max((int)((y - range) / tilesize / structQuadrantSize), 0); ry <= (int)((y + range) / tilesize / structQuadrantSize) && ry < quadHeight(); ry++){ + for(int rx = Math.max((int)((x - range) / tilesize / quadrantSize), 0); rx <= (int)((x + range) / tilesize / quadrantSize) && rx < quadWidth(); rx++){ + for(int ry = Math.max((int)((y - range) / tilesize / quadrantSize), 0); ry <= (int)((y + range) / tilesize / quadrantSize) && ry < quadHeight(); ry++){ if(!getQuad(team, rx, ry)) continue; - for(int tx = rx * structQuadrantSize; tx < (rx + 1) * structQuadrantSize && tx < world.width(); tx++){ - for(int ty = ry * structQuadrantSize; ty < (ry + 1) * structQuadrantSize && ty < world.height(); ty++){ + for(int tx = rx * quadrantSize; tx < (rx + 1) * quadrantSize && tx < world.width(); tx++){ + for(int ty = ry * quadrantSize; ty < (ry + 1) * quadrantSize && ty < world.height(); ty++){ Tile other = world.ltile(tx, ty); if(other == null) continue; @@ -196,7 +193,7 @@ public class BlockIndexer{ /** * Returns a set of tiles that have ores of the specified type nearby. * While each tile in the set is not guaranteed to have an ore directly on it, - * each tile will at least have an ore within {@link #oreQuadrantSize} / 2 blocks of it. + * each tile will at least have an ore within {@link #quadrantSize} / 2 blocks of it. * Only specific ore types are scanned. See {@link #scanOres}. */ public ObjectSet getOrePositions(Item item){ @@ -205,12 +202,12 @@ public class BlockIndexer{ /** Find the closest ore block relative to a position. */ public Tile findClosestOre(float xp, float yp, Item item){ - Tile tile = Geometry.findClosest(xp, yp, world.indexer.getOrePositions(item)); + Tile tile = Geometry.findClosest(xp, yp, getOrePositions(item)); if(tile == null) return null; - 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++){ + for(int x = Math.max(0, tile.x - quadrantSize / 2); x < tile.x + quadrantSize / 2 && x < world.width(); x++){ + for(int y = Math.max(0, tile.y - quadrantSize / 2); y < tile.y + quadrantSize / 2 && y < world.height(); y++){ Tile res = world.tile(x, y); if(res.block() == Blocks.air && res.drop() == item){ return res; @@ -222,8 +219,7 @@ public class BlockIndexer{ } private void process(Tile tile){ - if(tile.block().flags.size() > 0 && - tile.getTeam() != Team.none){ + if(tile.block().flags.size() > 0 && tile.getTeam() != Team.none){ ObjectSet[] map = getFlagged(tile.getTeam()); for(BlockFlag flag : tile.block().flags){ @@ -239,16 +235,16 @@ public class BlockIndexer{ if(ores == null) return; - int quadrantX = tile.x / oreQuadrantSize; - int quadrantY = tile.y / oreQuadrantSize; + int quadrantX = tile.x / quadrantSize; + int quadrantY = tile.y / quadrantSize; itemSet.clear(); - Tile rounded = world.tile(Mathf.clamp(quadrantX * oreQuadrantSize + oreQuadrantSize / 2, 0, world.width() - 1), - Mathf.clamp(quadrantY * oreQuadrantSize + oreQuadrantSize / 2, 0, world.height() - 1)); + Tile rounded = world.tile(Mathf.clamp(quadrantX * quadrantSize + quadrantSize / 2, 0, world.width() - 1), + Mathf.clamp(quadrantY * quadrantSize + quadrantSize / 2, 0, world.height() - 1)); //find all items that this quadrant contains - 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++){ + for(int x = quadrantX * quadrantSize; x < world.width() && x < (quadrantX + 1) * quadrantSize; x++){ + for(int y = quadrantY * quadrantSize; y < world.height() && y < (quadrantY + 1) * quadrantSize; y++){ Tile result = world.tile(x, y); if(result == null || result.drop() == null || !scanOres.contains(result.drop())) continue; @@ -273,8 +269,8 @@ public class BlockIndexer{ if(structQuadrants == null) return; //this quadrant is now 'dirty', re-scan the whole thing - int quadrantX = tile.x / structQuadrantSize; - int quadrantY = tile.y / structQuadrantSize; + int quadrantX = tile.x / quadrantSize; + int quadrantY = tile.y / quadrantSize; int index = quadrantX + quadrantY * quadWidth(); for(Team team : Team.all){ @@ -289,8 +285,8 @@ public class BlockIndexer{ structQuadrants[data.team.ordinal()].set(quadrantX, quadrantY, false); 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++){ + for(int x = quadrantX * quadrantSize; x < world.width() && x < (quadrantX + 1) * quadrantSize; x++){ + for(int y = quadrantY * quadrantSize; y < world.height() && y < (quadrantY + 1) * quadrantSize; y++){ Tile result = world.ltile(x, y); //when a targetable block is found, mark this quadrant as occupied and stop searching if(result.entity != null && result.getTeam() == data.team){ @@ -307,11 +303,11 @@ public class BlockIndexer{ } private int quadWidth(){ - return Mathf.ceil(world.width() / (float)structQuadrantSize); + return Mathf.ceil(world.width() / (float)quadrantSize); } private int quadHeight(){ - return Mathf.ceil(world.height() / (float)structQuadrantSize); + return Mathf.ceil(world.height() / (float)quadrantSize); } private void scanOres(){ @@ -324,8 +320,8 @@ public class BlockIndexer{ for(int x = 0; x < world.width(); x++){ for(int y = 0; y < world.height(); y++){ - int qx = (x / oreQuadrantSize); - int qy = (y / oreQuadrantSize); + int qx = (x / quadrantSize); + int qy = (y / quadrantSize); Tile tile = world.tile(x, y); @@ -333,8 +329,8 @@ public class BlockIndexer{ 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))); + Mathf.clamp(qx * quadrantSize + quadrantSize / 2, 0, world.width() - 1), + Mathf.clamp(qy * quadrantSize + quadrantSize / 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 8700ec6761..ee37db7460 100644 --- a/core/src/io/anuke/mindustry/ai/Pathfinder.java +++ b/core/src/io/anuke/mindustry/ai/Pathfinder.java @@ -5,7 +5,8 @@ import io.anuke.arc.collection.IntArray; import io.anuke.arc.collection.IntQueue; import io.anuke.arc.math.geom.Geometry; import io.anuke.arc.math.geom.Point2; -import io.anuke.arc.util.*; +import io.anuke.arc.util.Structs; +import io.anuke.arc.util.Time; import io.anuke.mindustry.game.EventType.TileChangeEvent; import io.anuke.mindustry.game.EventType.WorldLoadEvent; import io.anuke.mindustry.game.Team; @@ -95,7 +96,7 @@ public class Pathfinder{ */ private void update(Tile tile, Team team){ //make sure team exists - if(paths != null && paths[team.ordinal()] != null && paths[team.ordinal()].weights != null){ + if(paths != null && paths[team.ordinal()] != null && paths[team.ordinal()].weights != null && Structs.inBounds(tile.x, tile.y, paths[team.ordinal()].weights)){ PathData path = paths[team.ordinal()]; if(path.weights[tile.x][tile.y] <= 0.1f){ diff --git a/core/src/io/anuke/mindustry/ai/WaveSpawner.java b/core/src/io/anuke/mindustry/ai/WaveSpawner.java index bba51232c8..5863594f4f 100644 --- a/core/src/io/anuke/mindustry/ai/WaveSpawner.java +++ b/core/src/io/anuke/mindustry/ai/WaveSpawner.java @@ -2,6 +2,7 @@ package io.anuke.mindustry.ai; import io.anuke.arc.Events; import io.anuke.arc.collection.Array; +import io.anuke.arc.function.PositionConsumer; import io.anuke.arc.math.Angles; import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Time; @@ -19,6 +20,8 @@ import io.anuke.mindustry.world.Tile; import static io.anuke.mindustry.Vars.*; public class WaveSpawner{ + private static final float margin = 40f, coreMargin = tilesize * 3; //how far away from the edge flying units spawn + private Array flySpawns = new Array<>(); private Array groundSpawns = new Array<>(); private boolean spawning = false; @@ -46,28 +49,20 @@ public class WaveSpawner{ for(SpawnGroup group : state.rules.spawns){ int spawned = group.getUnitsSpawned(state.wave - 1); - float spawnX, spawnY; - float spread; - if(group.type.isFlying){ - for(FlyerSpawn spawn : flySpawns){ - float margin = 40f; //how far away from the edge flying units spawn - float trns = (world.width() + world.height()) * tilesize; - spawnX = Mathf.clamp(world.width() * tilesize / 2f + Angles.trnsx(spawn.angle, trns), -margin, world.width() * tilesize + margin); - spawnY = Mathf.clamp(world.height() * tilesize / 2f + Angles.trnsy(spawn.angle, trns), -margin, world.height() * tilesize + margin); - spread = margin / 1.5f; + float spread = margin / 1.5f; + eachFlyerSpawn((spawnX, spawnY) -> { for(int i = 0; i < spawned; i++){ BaseUnit unit = group.createUnit(waveTeam); unit.set(spawnX + Mathf.range(spread), spawnY + Mathf.range(spread)); unit.add(); } - } + }); }else{ - for(Tile spawn : groundSpawns){ - spawnX = spawn.worldx(); - spawnY = spawn.worldy(); - spread = tilesize * 2; + float spread = tilesize * 2; + + eachGroundSpawn((spawnX, spawnY, doShockwave) -> { for(int i = 0; i < spawned; i++){ Tmp.v1.rnd(spread); @@ -75,18 +70,51 @@ public class WaveSpawner{ BaseUnit unit = group.createUnit(waveTeam); unit.set(spawnX + Tmp.v1.x, spawnY + Tmp.v1.y); - Time.run(Math.min(i * 5, 60 * 2), () -> shockwave(unit)); + Time.run(Math.min(i * 5, 60 * 2), () -> spawnEffect(unit)); } - Time.run(20f, () -> Effects.effect(Fx.spawnShockwave, spawn.x * tilesize, spawn.y * tilesize, state.rules.dropZoneRadius)); - //would be interesting to see player structures survive this without hacks - Time.run(40f, () -> Damage.damage(waveTeam, spawn.x * tilesize, spawn.y * tilesize, state.rules.dropZoneRadius, 99999999f, true)); - } + }); } } + eachGroundSpawn((spawnX, spawnY, doShockwave) -> { + if(doShockwave){ + Time.run(20f, () -> Effects.effect(Fx.spawnShockwave, spawnX, spawnY, state.rules.dropZoneRadius)); + Time.run(40f, () -> Damage.damage(waveTeam, spawnX, spawnY, state.rules.dropZoneRadius, 99999999f, true)); + } + }); + Time.runTask(121f, () -> spawning = false); } + private void eachGroundSpawn(SpawnConsumer cons){ + for(Tile spawn : groundSpawns){ + cons.accept(spawn.worldx(), spawn.worldy(), true); + } + + if(state.rules.attackMode && state.teams.isActive(waveTeam) && !state.teams.get(defaultTeam).cores.isEmpty()){ + Tile firstCore = state.teams.get(defaultTeam).cores.first(); + for(Tile core : state.teams.get(waveTeam).cores){ + Tmp.v1.set(firstCore).sub(core.worldx(), core.worldy()).limit(coreMargin + core.block().size*tilesize); + cons.accept(core.worldx() + Tmp.v1.x, core.worldy() + Tmp.v1.y, false); + } + } + } + + private void eachFlyerSpawn(PositionConsumer cons){ + for(FlyerSpawn spawn : flySpawns){ + float trns = (world.width() + world.height()) * tilesize; + float spawnX = Mathf.clamp(world.width() * tilesize / 2f + Angles.trnsx(spawn.angle, trns), -margin, world.width() * tilesize + margin); + float spawnY = Mathf.clamp(world.height() * tilesize / 2f + Angles.trnsy(spawn.angle, trns), -margin, world.height() * tilesize + margin); + cons.accept(spawnX, spawnY); + } + + if(state.rules.attackMode && state.teams.isActive(waveTeam)){ + for(Tile core : state.teams.get(waveTeam).cores){ + cons.accept(core.worldx(), core.worldy()); + } + } + } + public boolean isSpawning(){ return spawning && !Net.client(); } @@ -114,7 +142,7 @@ public class WaveSpawner{ flySpawns.add(fspawn); } - private void shockwave(BaseUnit unit){ + private void spawnEffect(BaseUnit unit){ Effects.effect(Fx.unitSpawn, unit.x, unit.y, 0f, unit); Time.run(30f, () -> { unit.add(); @@ -122,11 +150,11 @@ public class WaveSpawner{ }); } + private interface SpawnConsumer{ + void accept(float x, float y, boolean shockwave); + } + private class FlyerSpawn{ float angle; } - - private class GroundSpawn{ - int x, y; - } } diff --git a/core/src/io/anuke/mindustry/content/Blocks.java b/core/src/io/anuke/mindustry/content/Blocks.java index 020128e9e9..a01af9f7b1 100644 --- a/core/src/io/anuke/mindustry/content/Blocks.java +++ b/core/src/io/anuke/mindustry/content/Blocks.java @@ -1,15 +1,19 @@ package io.anuke.mindustry.content; import io.anuke.arc.Core; +import io.anuke.arc.function.BooleanProvider; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.math.Mathf; +import io.anuke.arc.util.Tmp; import io.anuke.mindustry.Vars; +import io.anuke.mindustry.entities.Damage; +import io.anuke.mindustry.entities.bullet.Bullet; +import io.anuke.mindustry.entities.bullet.BulletType; import io.anuke.mindustry.game.ContentList; import io.anuke.mindustry.graphics.*; import io.anuke.mindustry.type.*; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.*; import io.anuke.mindustry.world.blocks.*; import io.anuke.mindustry.world.blocks.defense.*; import io.anuke.mindustry.world.blocks.defense.turrets.*; @@ -27,12 +31,14 @@ import static io.anuke.mindustry.Vars.state; import static io.anuke.mindustry.Vars.world; public class Blocks implements ContentList{ + public static final BooleanProvider padVisible = () -> state.rules.attackMode || state.rules.pvp || state.isEditor(); + public static Block //environment air, spawn, deepwater, water, taintedWater, tar, stone, craters, charr, sand, darksand, ice, snow, darksandTaintedWater, - holostone, rocks, sporerocks, icerocks, cliffs, sporePine, pine, shrubs, whiteTree, whiteTreeDead, sporeCluster, - iceSnow, sandWater, darksandWater, duneRocks, sandRocks, moss, sporeMoss, shale, shaleRocks, shaleBoulder, grass, salt, + holostone, rocks, sporerocks, icerocks, cliffs, sporePine, snowPine, pine, shrubs, whiteTree, whiteTreeDead, sporeCluster, + iceSnow, sandWater, darksandWater, duneRocks, sandRocks, moss, sporeMoss, shale, shaleRocks, shaleBoulder, sandBoulder, grass, salt, metalFloor, metalFloorDamaged, metalFloor2, metalFloor3, metalFloor5, ignarock, magmarock, hotrock, snowrocks, rock, snowrock, saltRocks, darkPanel1, darkPanel2, darkPanel3, darkPanel4, darkPanel5, darkPanel6, darkMetal, pebbles, tendrils, @@ -72,7 +78,7 @@ public class Blocks implements ContentList{ duo, scatter, scorch, hail, arc, wave, lancer, swarmer, salvo, fuse, ripple, cyclone, spectre, meltdown, //units - spiritFactory, phantomFactory, wraithFactory, ghoulFactory, revenantFactory, daggerFactory, crawlerFactory, titanFactory, + draugFactory, spiritFactory, phantomFactory, wraithFactory, ghoulFactory, revenantFactory, daggerFactory, crawlerFactory, titanFactory, fortressFactory, repairPoint, //upgrades @@ -305,11 +311,15 @@ public class Blocks implements ContentList{ saltRocks = new StaticWall("saltrocks"){{ }}; - sporePine = new StaticWall("spore-pine"){{ + sporePine = new StaticTree("spore-pine"){{ variants = 0; }}; - pine = new StaticWall("pine"){{ + snowPine = new StaticTree("snow-pine"){{ + variants = 0; + }}; + + pine = new StaticTree("pine"){{ variants = 0; }}; @@ -340,6 +350,10 @@ public class Blocks implements ContentList{ variants = 2; }}; + sandBoulder = new Rock("sand-boulder"){{ + variants = 2; + }}; + moss = new Floor("moss"){{ variants = 3; attributes.set(Attribute.spores, 0.15f); @@ -379,7 +393,7 @@ public class Blocks implements ContentList{ darkMetal = new StaticWall("dark-metal"); - pebbles = new OverlayFloor("pebbles"); + pebbles = new DoubleOverlayFloor("pebbles"); tendrils = new OverlayFloor("tendrils"); @@ -419,8 +433,8 @@ public class Blocks implements ContentList{ hasLiquids = true; hasPower = true; - consumes.power(2f); - consumes.item(Items.coal, 4); + consumes.power(1.8f); + consumes.item(Items.coal, 3); consumes.liquid(Liquids.water, 0.1f); }}; @@ -728,28 +742,33 @@ public class Blocks implements ContentList{ int wallHealthMultiplier = 4; scrapWall = new Wall("scrap-wall"){{ + requirements(Category.defense, () -> state.rules.infiniteResources, ItemStack.with()); health = 60 * wallHealthMultiplier; variants = 5; }}; scrapWallLarge = new Wall("scrap-wall-large"){{ + requirements(Category.defense, () -> state.rules.infiniteResources, ItemStack.with()); health = 60 * 4 * wallHealthMultiplier; size = 2; variants = 4; }}; scrapWallHuge = new Wall("scrap-wall-huge"){{ + requirements(Category.defense, () -> state.rules.infiniteResources, ItemStack.with()); health = 60 * 9 * wallHealthMultiplier; size = 3; variants = 3; }}; scrapWallGigantic = new Wall("scrap-wall-gigantic"){{ + requirements(Category.defense, () -> state.rules.infiniteResources, ItemStack.with()); health = 60 * 16 * wallHealthMultiplier; size = 4; }}; thruster = new Wall("thruster"){{ + requirements(Category.defense, () -> state.rules.infiniteResources, ItemStack.with()); health = 55 * 16 * wallHealthMultiplier; size = 4; }}; @@ -953,7 +972,7 @@ public class Blocks implements ContentList{ thermalPump = new Pump("thermal-pump"){{ requirements(Category.liquid, ItemStack.with(Items.copper, 160, Items.lead, 130, Items.silicon, 60, Items.titanium, 80, Items.thorium, 70)); - pumpAmount = 1.95f; + pumpAmount = 1.5f; consumes.power(0.30f); liquidCapacity = 40f; hasPower = true; @@ -1120,7 +1139,7 @@ public class Blocks implements ContentList{ }}; pneumaticDrill = new Drill("pneumatic-drill"){{ - requirements(Category.production, ItemStack.with(Items.copper, 60, Items.graphite, 50)); + requirements(Category.production, ItemStack.with(Items.copper, 35, Items.graphite, 15)); tier = 3; drillTime = 480; size = 2; @@ -1129,7 +1148,7 @@ public class Blocks implements ContentList{ }}; laserDrill = new Drill("laser-drill"){{ - requirements(Category.production, ItemStack.with(Items.copper, 70, Items.graphite, 90, Items.silicon, 60, Items.titanium, 50)); + requirements(Category.production, ItemStack.with(Items.copper, 70, Items.graphite, 60, Items.silicon, 60, Items.titanium, 40)); drillTime = 280; size = 3; hasPower = true; @@ -1142,8 +1161,8 @@ public class Blocks implements ContentList{ }}; blastDrill = new Drill("blast-drill"){{ - requirements(Category.production, ItemStack.with(Items.copper, 130, Items.silicon, 120, Items.titanium, 100, Items.thorium, 100)); - drillTime = 200; + requirements(Category.production, ItemStack.with(Items.copper, 130, Items.silicon, 120, Items.titanium, 100, Items.thorium, 150)); + drillTime = 270; size = 4; drawRim = true; hasPower = true; @@ -1173,14 +1192,14 @@ public class Blocks implements ContentList{ cultivator = new Cultivator("cultivator"){{ requirements(Category.production, ItemStack.with(Items.copper, 20, Items.lead, 50, Items.silicon, 20)); outputItem = new ItemStack(Items.sporePod, 1); - craftTime = 160; + craftTime = 140; size = 2; hasLiquids = true; hasPower = true; hasItems = true; consumes.power(0.80f); - consumes.liquid(Liquids.water, 0.15f); + consumes.liquid(Liquids.water, 0.18f); }}; oilExtractor = new Fracker("oil-extractor"){{ @@ -1207,7 +1226,7 @@ public class Blocks implements ContentList{ alwaysUnlocked = true; health = 1100; - itemCapacity = 5000; + itemCapacity = 4000; size = 3; }}; @@ -1248,7 +1267,7 @@ public class Blocks implements ContentList{ requirements(Category.effect, () -> world.isZone(), ItemStack.with(Items.copper, 500, Items.silicon, 150, Items.lead, 200)); size = 3; itemCapacity = 100; - launchTime = 60f * 8; + launchTime = 60f * 16; hasPower = true; consumes.power(1f); }}; @@ -1257,7 +1276,7 @@ public class Blocks implements ContentList{ requirements(Category.effect, () -> world.isZone(), ItemStack.with(Items.titanium, 400, Items.silicon, 300, Items.lead, 500, Items.plastanium, 150)); size = 4; itemCapacity = 250; - launchTime = 60f * 7; + launchTime = 60f * 14; hasPower = true; consumes.power(2f); }}; @@ -1290,8 +1309,8 @@ public class Blocks implements ContentList{ Items.scrap, Bullets.flakScrap, Items.lead, Bullets.flakLead ); - reload = 16f; - range = 175f; + reload = 18f; + range = 170f; size = 2; burstSpacing = 5f; shots = 2; @@ -1302,7 +1321,7 @@ public class Blocks implements ContentList{ inaccuracy = 17f; shootCone = 35f; - health = 260 * size * size; + health = 200 * size * size; }}; scorch = new ItemTurret("scorch"){{ @@ -1407,11 +1426,11 @@ public class Blocks implements ContentList{ Items.pyratite, Bullets.missileIncendiary, Items.surgealloy, Bullets.missileSurge ); - reload = 50f; + reload = 40f; shots = 4; burstSpacing = 5; inaccuracy = 10f; - range = 140f; + range = 185f; xRand = 6f; size = 2; health = 300 * size * size; @@ -1428,17 +1447,69 @@ public class Blocks implements ContentList{ ); size = 2; - range = 120f; - reload = 35f; + range = 150f; + reload = 30f; restitution = 0.03f; ammoEjectBack = 3f; cooldown = 0.03f; recoil = 3f; shootShake = 2f; - burstSpacing = 4; - shots = 3; + burstSpacing = 3f; + shots = 4; ammoUseEffect = Fx.shellEjectBig; - health = 360; + health = 240 * size * size;; + }}; + + fuse = new ItemTurret("fuse"){{ + requirements(Category.turret, ItemStack.with(Items.copper, 450, Items.graphite, 450, Items.thorium, 200)); + + reload = 35f; + shootShake = 4f; + range = 90f; + recoil = 5f; + shots = 3; + spread = 20f; + restitution = 0.1f; + shootCone = 30; + size = 3; + + health = 220 * size * size; + + ammo(Items.graphite, new BulletType(0.01f, 105){ + int rays = 1; + float rayLength = range + 10f; + + { + hitEffect = Fx.hitLancer; + shootEffect = smokeEffect = Fx.lightningShoot; + lifetime = 10f; + despawnEffect = Fx.none; + pierce = true; + } + + @Override + public void init(Bullet b){ + for(int i = 0; i < rays; i++){ + Damage.collideLine(b, b.getTeam(), hitEffect, b.x, b.y, b.rot(), rayLength - Math.abs(i - (rays / 2)) * 20f); + } + } + + @Override + public void draw(Bullet b){ + super.draw(b); + Draw.color(Color.WHITE, Pal.lancerLaser, b.fin()); + //Draw.alpha(b.fout()); + for(int i = 0; i < 7; i++){ + Tmp.v1.trns(b.rot(), i * 8f); + float sl = Mathf.clamp(b.fout() - 0.5f) * (80f - i * 10); + Shapes.tri(b.x + Tmp.v1.x, b.y + Tmp.v1.y, 4f, sl, b.rot() + 90); + Shapes.tri(b.x + Tmp.v1.x, b.y + Tmp.v1.y, 4f, sl, b.rot() - 90); + } + Shapes.tri(b.x, b.y, 20f * b.fout(), (rayLength + 50), b.rot()); + Shapes.tri(b.x, b.y, 20f * b.fout(), 10f, b.rot() + 180f); + Draw.reset(); + } + }); }}; ripple = new ArtilleryTurret("ripple"){{ @@ -1463,7 +1534,7 @@ public class Blocks implements ContentList{ shootShake = 2f; range = 290f; - health = 550; + health = 130 * size * size; }}; cyclone = new ItemTurret("cyclone"){{ @@ -1485,19 +1556,6 @@ public class Blocks implements ContentList{ health = 145 * size * size; }}; - fuse = new ItemTurret("fuse"){{ - requirements(Category.turret, ItemStack.with(Items.copper, 450, Items.graphite, 450, Items.surgealloy, 250)); - ammo(Items.graphite, Bullets.fuseShot); - reload = 40f; - shootShake = 4f; - range = 110f; - recoil = 5f; - restitution = 0.1f; - size = 3; - - health = 165 * size * size; - }}; - spectre = new DoubleTurret("spectre"){{ requirements(Category.turret, ItemStack.with(Items.copper, 700, Items.graphite, 600, Items.surgealloy, 500, Items.plastanium, 350, Items.thorium, 500)); ammo( @@ -1544,8 +1602,18 @@ public class Blocks implements ContentList{ //endregion //region units + draugFactory = new UnitFactory("draug-factory"){{ + requirements(Category.units, ItemStack.with(Items.copper, 60, Items.lead, 140)); + type = UnitTypes.draug; + produceTime = 5000; + size = 2; + maxSpawn = 2; + consumes.power(1.1f); + consumes.items(); + }}; + spiritFactory = new UnitFactory("spirit-factory"){{ - requirements(Category.units, ItemStack.with(Items.copper, 70, Items.lead, 110, Items.silicon, 80)); + requirements(Category.units, ItemStack.with(Items.metaglass, 70, Items.lead, 110, Items.silicon, 90)); type = UnitTypes.spirit; produceTime = 5700; size = 2; @@ -1565,72 +1633,73 @@ public class Blocks implements ContentList{ }}; wraithFactory = new UnitFactory("wraith-factory"){{ - requirements(Category.units, ItemStack.with(Items.titanium, 60, Items.lead, 80, Items.silicon, 90)); + requirements(Category.units, padVisible, ItemStack.with(Items.titanium, 60, Items.lead, 80, Items.silicon, 90)); type = UnitTypes.wraith; - produceTime = 1800; + produceTime = 1500; size = 2; - consumes.power(1f); - consumes.items(new ItemStack(Items.silicon, 10), new ItemStack(Items.titanium, 10)); + consumes.power(0.6f); + consumes.items(new ItemStack(Items.silicon, 20), new ItemStack(Items.titanium, 10)); }}; ghoulFactory = new UnitFactory("ghoul-factory"){{ - requirements(Category.units, ItemStack.with(Items.plastanium, 80, Items.titanium, 100, Items.lead, 130, Items.silicon, 220)); + requirements(Category.units, padVisible, ItemStack.with(Items.titanium, 150, Items.lead, 130, Items.silicon, 220)); type = UnitTypes.ghoul; - produceTime = 3600; + produceTime = 2300; size = 3; - consumes.power(2f); - consumes.items(new ItemStack(Items.silicon, 30), new ItemStack(Items.titanium, 30), new ItemStack(Items.plastanium, 20)); + consumes.power(1.2f); + consumes.items(new ItemStack(Items.silicon, 30), new ItemStack(Items.titanium, 20)); }}; revenantFactory = new UnitFactory("revenant-factory"){{ - requirements(Category.units, ItemStack.with(Items.plastanium, 300, Items.titanium, 400, Items.lead, 300, Items.silicon, 400, Items.surgealloy, 100)); + requirements(Category.units, padVisible, ItemStack.with(Items.plastanium, 100, Items.titanium, 300, Items.lead, 300, Items.silicon, 400)); type = UnitTypes.revenant; - produceTime = 8000; + produceTime = 4000; size = 4; consumes.power(3f); - consumes.items(new ItemStack(Items.silicon, 80), new ItemStack(Items.titanium, 80), new ItemStack(Items.plastanium, 50)); + consumes.items(new ItemStack(Items.silicon, 80), new ItemStack(Items.titanium, 80)); }}; daggerFactory = new UnitFactory("dagger-factory"){{ - requirements(Category.units, ItemStack.with(Items.lead, 90, Items.silicon, 70)); + requirements(Category.units, padVisible, ItemStack.with(Items.lead, 110, Items.silicon, 70)); type = UnitTypes.dagger; produceTime = 1700; size = 2; - consumes.power(0.50f); - consumes.items(new ItemStack(Items.silicon, 10)); + consumes.power(0.5f); + consumes.items(new ItemStack(Items.silicon, 15)); }}; crawlerFactory = new UnitFactory("crawler-factory"){{ - requirements(Category.units, ItemStack.with(Items.lead, 100, Items.silicon, 80)); + requirements(Category.units, padVisible, ItemStack.with(Items.lead, 50, Items.silicon, 80)); type = UnitTypes.crawler; - produceTime = 1200; + produceTime = 500; size = 2; - consumes.power(0.4f); - consumes.items(new ItemStack(Items.blastCompound, 10)); + maxSpawn = 5; + consumes.power(0.5f); + consumes.items(new ItemStack(Items.coal, 5), new ItemStack(Items.silicon, 5)); }}; titanFactory = new UnitFactory("titan-factory"){{ - requirements(Category.units, ItemStack.with(Items.thorium, 90, Items.lead, 140, Items.silicon, 90)); + requirements(Category.units, padVisible, ItemStack.with(Items.graphite, 100, Items.lead, 100, Items.silicon, 90)); type = UnitTypes.titan; - produceTime = 3400; + produceTime = 2100; size = 3; - consumes.power(1.50f); - consumes.items(new ItemStack(Items.silicon, 20), new ItemStack(Items.thorium, 30)); + consumes.power(0.60f); + consumes.items(new ItemStack(Items.silicon, 30)); }}; fortressFactory = new UnitFactory("fortress-factory"){{ - requirements(Category.units, ItemStack.with(Items.thorium, 200, Items.lead, 220, Items.silicon, 150, Items.surgealloy, 100, Items.phasefabric, 50)); + requirements(Category.units, padVisible, ItemStack.with(Items.thorium, 80, Items.lead, 220, Items.silicon, 150)); type = UnitTypes.fortress; - produceTime = 5000; + produceTime = 4000; size = 3; maxSpawn = 3; - consumes.power(2f); - consumes.items(new ItemStack(Items.silicon, 40), new ItemStack(Items.thorium, 50)); + consumes.power(1.4f); + consumes.items(new ItemStack(Items.silicon, 40), new ItemStack(Items.graphite, 30)); }}; repairPoint = new RepairPoint("repair-point"){{ requirements(Category.units, ItemStack.with(Items.lead, 30, Items.copper, 30, Items.silicon, 30)); - repairSpeed = 0.1f; + repairSpeed = 0.3f; powerUse = 1f; }}; diff --git a/core/src/io/anuke/mindustry/content/Bullets.java b/core/src/io/anuke/mindustry/content/Bullets.java index c3e69f9dc1..13d4496693 100644 --- a/core/src/io/anuke/mindustry/content/Bullets.java +++ b/core/src/io/anuke/mindustry/content/Bullets.java @@ -12,7 +12,6 @@ import io.anuke.mindustry.entities.effect.*; import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.game.ContentList; import io.anuke.mindustry.graphics.Pal; -import io.anuke.mindustry.graphics.Shapes; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.BuildBlock; @@ -41,7 +40,7 @@ public class Bullets implements ContentList{ waterShot, cryoShot, slagShot, oilShot, //environment, misc. - fireball, basicFlame, pyraFlame, fuseShot, driverBolt, healBullet, frag, eruptorShot, + fireball, basicFlame, pyraFlame, driverBolt, healBullet, frag, eruptorShot, //bombs bombExplosive, bombIncendiary, bombOil, explode; @@ -116,6 +115,7 @@ public class Bullets implements ContentList{ lifetime = 70f; bulletWidth = bulletHeight = 14f; collidesTiles = false; + ammoMultiplier = 2f; splashDamageRadius = 45f; splashDamage = 50f; backColor = Pal.missileYellowBack; @@ -142,7 +142,7 @@ public class Bullets implements ContentList{ bulletWidth = 6f; bulletHeight = 8f; hitEffect = Fx.flakExplosion; - splashDamage = 35f; + splashDamage = 27f; splashDamageRadius = 15f; }}; @@ -154,7 +154,7 @@ public class Bullets implements ContentList{ bulletWidth = 6f; bulletHeight = 8f; hitEffect = Fx.flakExplosion; - splashDamage = 26f; + splashDamage = 22f; splashDamageRadius = 24f; }}; @@ -171,6 +171,7 @@ public class Bullets implements ContentList{ flakExplosive = new FlakBulletType(4f, 5){{ //default bullet type, no changes shootEffect = Fx.shootBig; + ammoMultiplier = 2f; }}; flakSurge = new FlakBulletType(4f, 7){{ @@ -180,19 +181,20 @@ public class Bullets implements ContentList{ shootEffect = Fx.shootBig; }}; - missileExplosive = new MissileBulletType(1.8f, 10, "missile"){{ + missileExplosive = new MissileBulletType(2.7f, 10, "missile"){{ bulletWidth = 8f; bulletHeight = 8f; bulletShrink = 0f; drag = -0.01f; splashDamageRadius = 30f; splashDamage = 30f; + ammoMultiplier = 2f; lifetime = 150f; hitEffect = Fx.blastExplosion; despawnEffect = Fx.blastExplosion; }}; - missileIncendiary = new MissileBulletType(2f, 12, "missile"){{ + missileIncendiary = new MissileBulletType(2.9f, 12, "missile"){{ frontColor = Pal.lightishOrange; backColor = Pal.lightOrange; bulletWidth = 7f; @@ -208,7 +210,7 @@ public class Bullets implements ContentList{ incendAmount = 3; }}; - missileSurge = new MissileBulletType(3.5f, 15, "bullet"){{ + missileSurge = new MissileBulletType(4.4f, 15, "bullet"){{ bulletWidth = 8f; bulletHeight = 8f; bulletShrink = 0f; @@ -281,6 +283,7 @@ public class Bullets implements ContentList{ standardCopper = new BasicBulletType(2.5f, 9, "bullet"){{ bulletWidth = 7f; bulletHeight = 9f; + lifetime = 60f; shootEffect = Fx.shootSmall; smokeEffect = Fx.shootSmallSmoke; ammoMultiplier = 1; @@ -291,6 +294,7 @@ public class Bullets implements ContentList{ bulletHeight = 12f; reloadMultiplier = 0.6f; ammoMultiplier = 2; + lifetime = 60f; }}; standardThorium = new BasicBulletType(4f, 29, "bullet"){{ @@ -299,6 +303,7 @@ public class Bullets implements ContentList{ shootEffect = Fx.shootBig; smokeEffect = Fx.shootBigSmoke; ammoMultiplier = 2; + lifetime = 60f; }}; standardHoming = new BasicBulletType(3f, 9, "bullet"){{ @@ -307,6 +312,7 @@ public class Bullets implements ContentList{ homingPower = 5f; reloadMultiplier = 1.4f; ammoMultiplier = 3; + lifetime = 60f; }}; standardIncendiary = new BasicBulletType(3.2f, 11, "bullet"){{ @@ -318,6 +324,7 @@ public class Bullets implements ContentList{ incendAmount = 1; incendChance = 0.3f; inaccuracy = 3f; + lifetime = 60f; }}; standardGlaive = new BasicBulletType(4f, 7.5f, "bullet"){{ @@ -328,6 +335,7 @@ public class Bullets implements ContentList{ incendSpread = 3f; incendAmount = 1; incendChance = 0.3f; + lifetime = 60f; }}; standardMechSmall = new BasicBulletType(4f, 9, "bullet"){{ @@ -400,7 +408,7 @@ public class Bullets implements ContentList{ super.hit(b); tile = tile.link(); - if(tile.getTeam() == b.getTeam() && !(tile.block() instanceof BuildBlock)){ + if(tile.entity != null && tile.getTeam() == b.getTeam() && !(tile.block() instanceof BuildBlock)){ Effects.effect(Fx.healBlockFull, Pal.heal, tile.drawx(), tile.drawy(), tile.block().size); tile.entity.healBy(healPercent / 100f * tile.entity.maxHealth()); } @@ -577,42 +585,6 @@ public class Bullets implements ContentList{ } }; - fuseShot = new BulletType(0.01f, 70){ - int rays = 3; - float rayLength = 120f; - - { - hitEffect = Fx.hitFuse; - shootEffect = smokeEffect = Fx.none; - lifetime = 10f; - despawnEffect = Fx.none; - pierce = true; - } - - @Override - public void init(Bullet b){ - for(int i = 0; i < rays; i++){ - Damage.collideLine(b, b.getTeam(), hitEffect, b.x, b.y, b.rot(), rayLength - Math.abs(i - (rays / 2)) * 20f); - } - } - - @Override - public void draw(Bullet b){ - super.draw(b); - Draw.color(Color.WHITE, Pal.surge, b.fin()); - //Draw.alpha(b.fout()); - for(int i = 0; i < 7; i++){ - Tmp.v1.trns(b.rot(), i * 8f); - float sl = Mathf.clamp(b.fout() - 0.5f) * (80f - i * 10); - Shapes.tri(b.x + Tmp.v1.x, b.y + Tmp.v1.y, 4f, sl, b.rot() + 90); - Shapes.tri(b.x + Tmp.v1.x, b.y + Tmp.v1.y, 4f, sl, b.rot() - 90); - } - Shapes.tri(b.x, b.y, 20f * b.fout(), (rayLength + 50), b.rot()); - Shapes.tri(b.x, b.y, 20f * b.fout(), 10f, b.rot() + 180f); - Draw.reset(); - } - }; - waterShot = new LiquidBulletType(Liquids.water){{ knockback = 0.7f; }}; diff --git a/core/src/io/anuke/mindustry/content/Fx.java b/core/src/io/anuke/mindustry/content/Fx.java index 7b0771eb28..b8164ee735 100644 --- a/core/src/io/anuke/mindustry/content/Fx.java +++ b/core/src/io/anuke/mindustry/content/Fx.java @@ -37,8 +37,7 @@ public class Fx implements ContentList{ @Override public void load(){ - none = new Effect(0, 0f, e -> { - }); + none = new Effect(0, 0f, e -> {}); unitSpawn = new Effect(30f, e -> { if(!(e.data instanceof BaseUnit)) return; @@ -444,10 +443,10 @@ public class Fx implements ContentList{ Draw.color(); }); - fire = new Effect(35f, e -> { + fire = new Effect(50f, e -> { Draw.color(Pal.lightFlame, Pal.darkFlame, e.fin()); - Angles.randLenVectors(e.id, 2, 2f + e.fin() * 7f, (x, y) -> { + Angles.randLenVectors(e.id, 2, 2f + e.fin() * 9f, (x, y) -> { Fill.circle(e.x + x, e.y + y, 0.2f + e.fslope() * 1.5f); }); @@ -583,7 +582,7 @@ public class Fx implements ContentList{ spawnShockwave = new Effect(20f, 400f, e -> { Draw.color(Color.WHITE, Color.LIGHT_GRAY, e.fin()); Lines.stroke(e.fout() * 3f + 0.5f); - Lines.poly(e.x, e.y, 60, e.fin() * (e.rotation + 50f)); + Lines.poly(e.x, e.y, 40, e.fin() * (e.rotation + 50f)); Draw.reset(); }); @@ -792,8 +791,9 @@ public class Fx implements ContentList{ Draw.color(Color.LIGHT_GRAY, Color.GRAY, e.fin()); for(int i : Mathf.signs){ + float ex = e.x, ey = e.y, fout = e.fout(); Angles.randLenVectors(e.id, 4, 1f + e.finpow() * 11f, e.rotation + 90f * i, 20f, (x, y) -> { - Fill.circle(e.x + x, e.y + y, e.fout() * 1.5f); + Fill.circle(ex + x, ey + y, fout * 1.5f); }); } @@ -816,8 +816,9 @@ public class Fx implements ContentList{ Draw.color(Color.LIGHT_GRAY); for(int i : Mathf.signs){ + float ex = e.x, ey = e.y, fout = e.fout(); Angles.randLenVectors(e.id, 4, -e.finpow() * 15f, e.rotation + 90f * i, 25f, (x, y) -> { - Fill.circle(e.x + x, e.y + y, e.fout() * 2f); + Fill.circle(ex + x, ey + y, fout * 2f); }); } diff --git a/core/src/io/anuke/mindustry/content/Items.java b/core/src/io/anuke/mindustry/content/Items.java index 6ee41034c2..b8c567bfcc 100644 --- a/core/src/io/anuke/mindustry/content/Items.java +++ b/core/src/io/anuke/mindustry/content/Items.java @@ -85,7 +85,7 @@ public class Items implements ContentList{ }}; sporePod = new Item("spore-pod", Color.valueOf("7457ce")){{ - flammability = 1.05f; + flammability = 1.15f; }}; blastCompound = new Item("blast-compound", Color.valueOf("ff795e")){{ diff --git a/core/src/io/anuke/mindustry/content/Mechs.java b/core/src/io/anuke/mindustry/content/Mechs.java index af6448725a..801029bae9 100644 --- a/core/src/io/anuke/mindustry/content/Mechs.java +++ b/core/src/io/anuke/mindustry/content/Mechs.java @@ -71,7 +71,7 @@ public class Mechs implements ContentList{ weapon = new Weapon("shockgun"){{ shake = 2f; length = 1f; - reload = 45f; + reload = 55f; shotDelay = 3f; roundrobin = true; shots = 2; @@ -159,12 +159,12 @@ public class Mechs implements ContentList{ weaponOffsetX = 1; weaponOffsetY = 0; engineColor = Color.valueOf("feb380"); - health = 320f; + health = 350f; buildPower = 1.5f; weapon = new Weapon("swarmer"){{ length = 1.5f; recoil = 4f; - reload = 45f; + reload = 38f; shots = 4; spacing = 8f; inaccuracy = 8f; diff --git a/core/src/io/anuke/mindustry/content/TechTree.java b/core/src/io/anuke/mindustry/content/TechTree.java index caf1ebeb4b..8228b78eb2 100644 --- a/core/src/io/anuke/mindustry/content/TechTree.java +++ b/core/src/io/anuke/mindustry/content/TechTree.java @@ -246,8 +246,28 @@ public class TechTree implements ContentList{ }); }); - node(spiritFactory, () -> { - node(phantomFactory); + node(draugFactory, () -> { + node(spiritFactory, () -> { + node(phantomFactory); + }); + + node(daggerFactory, () -> { + node(crawlerFactory, () -> { + node(titanFactory, () -> { + node(fortressFactory, () -> { + + }); + }); + }); + + node(wraithFactory, () -> { + node(ghoulFactory, () -> { + node(revenantFactory, () -> { + + }); + }); + }); + }); }); node(dartPad, () -> { diff --git a/core/src/io/anuke/mindustry/content/TypeIDs.java b/core/src/io/anuke/mindustry/content/TypeIDs.java new file mode 100644 index 0000000000..faf82ed359 --- /dev/null +++ b/core/src/io/anuke/mindustry/content/TypeIDs.java @@ -0,0 +1,18 @@ +package io.anuke.mindustry.content; + +import io.anuke.mindustry.entities.effect.Fire; +import io.anuke.mindustry.entities.effect.Puddle; +import io.anuke.mindustry.entities.type.Player; +import io.anuke.mindustry.game.ContentList; +import io.anuke.mindustry.game.TypeID; + +public class TypeIDs implements ContentList{ + public static TypeID fire, puddle, player; + + @Override + public void load(){ + fire = new TypeID("fire", Fire::new); + puddle = new TypeID("puddle", Puddle::new); + player = new TypeID("player", Player::new); + } +} diff --git a/core/src/io/anuke/mindustry/content/UnitTypes.java b/core/src/io/anuke/mindustry/content/UnitTypes.java index 217e8227ee..54fcf2ceb8 100644 --- a/core/src/io/anuke/mindustry/content/UnitTypes.java +++ b/core/src/io/anuke/mindustry/content/UnitTypes.java @@ -8,17 +8,32 @@ import io.anuke.mindustry.type.Weapon; public class UnitTypes implements ContentList{ public static UnitType - spirit, phantom, + draug, spirit, phantom, wraith, ghoul, revenant, lich, reaper, dagger, crawler, titan, fortress, eruptor, chaosArray, eradicator; @Override public void load(){ + draug = new UnitType("draug", Draug.class, Draug::new){{ + isFlying = true; + drag = 0.01f; + speed = 0.3f; + maxVelocity = 1.2f; + range = 50f; + health = 60; + minePower = 0.5f; + engineSize = 1.8f; + engineOffset = 5.7f; + weapon = new Weapon("you have incurred my wrath. prepare to die."){{ + bullet = Bullets.lancerLaser; + }}; + }}; + spirit = new UnitType("spirit", Spirit.class, Spirit::new){{ isFlying = true; drag = 0.01f; - speed = 0.2f; - maxVelocity = 0.8f; + speed = 0.4f; + maxVelocity = 1.6f; range = 50f; health = 60; engineSize = 1.8f; @@ -34,6 +49,30 @@ public class UnitTypes implements ContentList{ }}; }}; + phantom = new UnitType("phantom", Phantom.class, Phantom::new){{ + isFlying = true; + drag = 0.01f; + mass = 2f; + speed = 0.45f; + maxVelocity = 1.9f; + range = 70f; + itemCapacity = 70; + health = 220; + buildPower = 0.9f; + minePower = 1.1f; + engineOffset = 6.5f; + toMine = ObjectSet.with(Items.lead, Items.copper, Items.titanium); + weapon = new Weapon("heal-blaster"){{ + length = 1.5f; + reload = 20f; + width = 0.5f; + roundrobin = true; + ejectEffect = Fx.none; + recoil = 2f; + bullet = Bullets.healBullet; + }}; + }}; + dagger = new UnitType("dagger", Dagger.class, Dagger::new){{ maxVelocity = 1.1f; speed = 0.2f; @@ -51,8 +90,8 @@ public class UnitTypes implements ContentList{ }}; crawler = new UnitType("crawler", Crawler.class, Crawler::new){{ - maxVelocity = 1.2f; - speed = 0.26f; + maxVelocity = 1.25f; + speed = 0.28f; drag = 0.4f; hitsize = 8f; mass = 1.75f; @@ -213,30 +252,6 @@ public class UnitTypes implements ContentList{ }}; }}; - phantom = new UnitType("phantom", Phantom.class, Phantom::new){{ - isFlying = true; - drag = 0.01f; - mass = 2f; - speed = 0.2f; - maxVelocity = 0.9f; - range = 70f; - itemCapacity = 70; - health = 220; - buildPower = 0.9f; - minePower = 1.1f; - engineOffset = 6.5f; - toMine = ObjectSet.with(Items.lead, Items.copper, Items.titanium); - weapon = new Weapon("heal-blaster"){{ - length = 1.5f; - reload = 20f; - width = 0.5f; - roundrobin = true; - ejectEffect = Fx.none; - recoil = 2f; - bullet = Bullets.healBullet; - }}; - }}; - revenant = new UnitType("revenant", Revenant.class, Revenant::new){{ health = 1000; mass = 5f; @@ -288,6 +303,7 @@ public class UnitTypes implements ContentList{ reload = 180f; width = 22f; shots = 22; + shootCone = 100f; shotDelay = 2; inaccuracy = 10f; roundrobin = true; @@ -318,6 +334,7 @@ public class UnitTypes implements ContentList{ reload = 10f; width = 32f; shots = 1; + shootCone = 100f; shake = 1f; inaccuracy = 3f; diff --git a/core/src/io/anuke/mindustry/content/Zones.java b/core/src/io/anuke/mindustry/content/Zones.java index e8e3933150..6cc126c37a 100644 --- a/core/src/io/anuke/mindustry/content/Zones.java +++ b/core/src/io/anuke/mindustry/content/Zones.java @@ -1,7 +1,8 @@ package io.anuke.mindustry.content; import io.anuke.arc.collection.Array; -import io.anuke.mindustry.game.*; +import io.anuke.mindustry.game.ContentList; +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.maps.zonegen.DesertWastesGenerator; @@ -12,24 +13,19 @@ public class Zones implements ContentList{ public static Zone groundZero, desertWastes, craters, frozenForest, ruinousShores, stainedMountains, tarFields, - saltFlats, overgrowth, infestedIslands, + saltFlats, overgrowth, impact0078, crags, desolateRift, nuclearComplex; @Override public void load(){ - groundZero = new Zone("groundZero", new MapGenerator("groundZero", 1).decor(new Decoration(Blocks.snow, Blocks.snowrock, 0.01))){{ + groundZero = new Zone("groundZero", new MapGenerator("groundZero", 1)){{ baseLaunchCost = ItemStack.with(Items.copper, -100); startingItems = ItemStack.list(Items.copper, 100); alwaysUnlocked = true; conditionWave = 5; launchPeriod = 5; resources = new Item[]{Items.copper, Items.scrap, Items.lead}; - rules = () -> new Rules(){{ - waves = true; - waveTimer = true; - waveSpacing = 60 * 60 * 2; - }}; }}; desertWastes = new Zone("desertWastes", new DesertWastesGenerator(260, 260)){{ @@ -38,13 +34,14 @@ public class Zones implements ContentList{ launchPeriod = 10; loadout = Loadouts.advancedShard; zoneRequirements = ZoneRequirement.with(groundZero, 20); + blockRequirements = new Block[]{Blocks.combustionGenerator}; resources = new Item[]{Items.copper, Items.lead, Items.coal, Items.sand}; - rules = () -> new Rules(){{ - waves = true; - waveTimer = true; - launchWaveMultiplier = 3f; - waveSpacing = 60 * 50f; - spawns = Array.with( + rules = r -> { + r.waves = true; + r.waveTimer = true; + r.launchWaveMultiplier = 3f; + r.waveSpacing = 60 * 50f; + r.spawns = Array.with( new SpawnGroup(UnitTypes.crawler){{ unitScaling = 3f; }}, @@ -77,35 +74,19 @@ public class Zones implements ContentList{ spacing = 20; }} ); - }}; + }; }}; - //to be implemented as an attack map - /* - saltFlats = new Zone("saltFlats", new DesertWastesGenerator(260, 260)){{ - startingItems = ItemStack.list(Items.copper, 200); - conditionWave = 10; - zoneRequirements = ZoneRequirement.with(desertWastes, 25); - blockRequirements = new Block[]{Blocks.router}; - resources = new Item[]{Items.copper, Items.lead, Items.coal, Items.sand}; - rules = () -> new Rules(){{ - waves = true; - waveTimer = true; - waveSpacing = 60 * 60 * 1.5f; - }}; - }};*/ - - craters = new Zone("craters", new MapGenerator("craters", 1).dist(0).decor(new Decoration(Blocks.snow, Blocks.sporeCluster, 0.01))){{ - startingItems = ItemStack.list(Items.copper, 200); - conditionWave = 10; - zoneRequirements = ZoneRequirement.with(groundZero, 10); - blockRequirements = new Block[]{Blocks.router}; - resources = new Item[]{Items.copper, Items.lead, Items.coal}; - rules = () -> new Rules(){{ - waves = true; - waveTimer = true; - waveSpacing = 60 * 60 * 1.5f; - }}; + saltFlats = new Zone("saltFlats", new MapGenerator("saltFlats")){{ + baseLaunchCost = ItemStack.with(Items.copper, -100); + startingItems = ItemStack.list(Items.copper, 100); + alwaysUnlocked = true; + conditionWave = 5; + launchPeriod = 5; + loadout = Loadouts.basicFoundation; + zoneRequirements = ZoneRequirement.with(desertWastes, 60); + blockRequirements = new Block[]{Blocks.daggerFactory, Blocks.draugFactory}; + resources = new Item[]{Items.copper, Items.scrap, Items.lead, Items.coal, Items.sand}; }}; frozenForest = new Zone("frozenForest", new MapGenerator("frozenForest", 1) @@ -114,13 +95,17 @@ public class Zones implements ContentList{ baseLaunchCost = ItemStack.with(); startingItems = ItemStack.list(Items.copper, 400); conditionWave = 10; - zoneRequirements = ZoneRequirement.with(craters, 10); + blockRequirements = new Block[]{Blocks.junction, Blocks.router}; + zoneRequirements = ZoneRequirement.with(groundZero, 10); resources = new Item[]{Items.copper, Items.lead, Items.coal}; - rules = () -> new Rules(){{ - waves = true; - waveTimer = true; - waveSpacing = 60 * 60 * 1.5f; - }}; + }}; + + craters = new Zone("craters", new MapGenerator("craters", 1).dist(0).decor(new Decoration(Blocks.snow, Blocks.sporeCluster, 0.004))){{ + startingItems = ItemStack.list(Items.copper, 200); + conditionWave = 10; + zoneRequirements = ZoneRequirement.with(frozenForest, 10); + blockRequirements = new Block[]{Blocks.mender, Blocks.combustionGenerator}; + resources = new Item[]{Items.copper, Items.lead, Items.coal, Items.sand, Items.scrap}; }}; overgrowth = new Zone("overgrowth", new MapGenerator("overgrowth")){{ @@ -128,14 +113,9 @@ public class Zones implements ContentList{ conditionWave = 12; launchPeriod = 4; loadout = Loadouts.basicNucleus; - zoneRequirements = ZoneRequirement.with(frozenForest, 40); - blockRequirements = new Block[]{Blocks.router}; + zoneRequirements = ZoneRequirement.with(craters, 40); + blockRequirements = new Block[]{Blocks.cultivator, Blocks.sporePress}; resources = new Item[]{Items.copper, Items.lead, Items.coal, Items.titanium, Items.sand, Items.thorium, Items.scrap}; - rules = () -> new Rules(){{ - waves = true; - waveTimer = true; - waveSpacing = 60 * 100f; - }}; }}; ruinousShores = new Zone("ruinousShores", new MapGenerator("ruinousShores", 1).dist(3f, true)){{ @@ -145,13 +125,8 @@ public class Zones implements ContentList{ conditionWave = 20; launchPeriod = 20; zoneRequirements = ZoneRequirement.with(desertWastes, 20, craters, 15); - blockRequirements = new Block[]{Blocks.graphitePress, Blocks.combustionGenerator}; + blockRequirements = new Block[]{Blocks.graphitePress, Blocks.combustionGenerator, Blocks.kiln}; resources = new Item[]{Items.copper, Items.scrap, Items.lead, Items.coal, Items.sand}; - rules = () -> new Rules(){{ - waves = true; - waveTimer = true; - waveSpacing = 60 * 80; - }}; }}; stainedMountains = new Zone("stainedMountains", new MapGenerator("stainedMountains", 2) @@ -164,11 +139,6 @@ public class Zones implements ContentList{ zoneRequirements = ZoneRequirement.with(frozenForest, 15); blockRequirements = new Block[]{Blocks.pneumaticDrill}; resources = new Item[]{Items.copper, Items.scrap, Items.lead, Items.coal, Items.titanium, Items.sand}; - rules = () -> new Rules(){{ - waves = true; - waveTimer = true; - waveSpacing = 60 * 60 * 2; - }}; }}; tarFields = new Zone("tarFields", new MapGenerator("tarFields") @@ -181,11 +151,6 @@ public class Zones implements ContentList{ zoneRequirements = ZoneRequirement.with(ruinousShores, 20); blockRequirements = new Block[]{Blocks.coalCentrifuge}; resources = new Item[]{Items.copper, Items.scrap, Items.lead, Items.coal, Items.titanium, Items.sand}; - rules = () -> new Rules(){{ - waves = true; - waveTimer = true; - waveSpacing = 60 * 60 * 2; - }}; }}; desolateRift = new Zone("desolateRift", new MapGenerator("desolateRift").dist(2f)){{ @@ -197,13 +162,20 @@ public class Zones implements ContentList{ zoneRequirements = ZoneRequirement.with(tarFields, 20); blockRequirements = new Block[]{Blocks.thermalGenerator}; resources = new Item[]{Items.copper, Items.scrap, Items.lead, Items.coal, Items.titanium, Items.sand, Items.thorium}; - rules = () -> new Rules(){{ - waves = true; - waveTimer = true; - waveSpacing = 60 * 60 * 2.5f; - }}; }}; + /* + crags = new Zone("crags", new MapGenerator("crags").dist(2f)){{ + loadout = Loadouts.basicFoundation; + baseLaunchCost = ItemStack.with(); + startingItems = ItemStack.list(Items.copper, 2000, Items.lead, 2000, Items.graphite, 500, Items.titanium, 500, Items.silicon, 500); + conditionWave = 3; + launchPeriod = 2; + zoneRequirements = ZoneRequirement.with(stainedMountains, 40); + blockRequirements = new Block[]{Blocks.thermalGenerator}; + resources = new Item[]{Items.copper, Items.scrap, Items.lead, Items.coal, Items.sand}; + }};*/ + nuclearComplex = new Zone("nuclearComplex", new MapGenerator("nuclearProductionComplex", 1) .decor(new Decoration(Blocks.snow, Blocks.sporeCluster, 0.01))){{ loadout = Loadouts.basicNucleus; @@ -212,13 +184,20 @@ public class Zones implements ContentList{ conditionWave = 30; launchPeriod = 15; zoneRequirements = ZoneRequirement.with(stainedMountains, 20); - blockRequirements = new Block[]{Blocks.thermalGenerator}; + blockRequirements = new Block[]{Blocks.thermalGenerator, Blocks.laserDrill}; 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; - }}; }}; + + /* + impact0078 = new Zone("impact0078", new MapGenerator("impact0078").dist(2f)){{ + loadout = Loadouts.basicNucleus; + baseLaunchCost = ItemStack.with(); + startingItems = ItemStack.list(Items.copper, 2000, Items.lead, 2000, Items.graphite, 500, Items.titanium, 500, Items.silicon, 500); + conditionWave = 3; + launchPeriod = 2; + zoneRequirements = ZoneRequirement.with(nuclearComplex, 40); + blockRequirements = new Block[]{Blocks.thermalGenerator}; + resources = new Item[]{Items.copper, Items.scrap, Items.lead, Items.coal, Items.titanium, Items.thorium}; + }};*/ } } diff --git a/core/src/io/anuke/mindustry/core/ContentLoader.java b/core/src/io/anuke/mindustry/core/ContentLoader.java index e936c347c7..6e085668f0 100644 --- a/core/src/io/anuke/mindustry/core/ContentLoader.java +++ b/core/src/io/anuke/mindustry/core/ContentLoader.java @@ -6,11 +6,7 @@ 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.bullet.Bullet; import io.anuke.mindustry.entities.bullet.BulletType; -import io.anuke.mindustry.entities.effect.*; -import io.anuke.mindustry.entities.traits.TypeTrait; -import io.anuke.mindustry.entities.type.Player; import io.anuke.mindustry.game.*; import io.anuke.mindustry.type.*; import io.anuke.mindustry.world.Block; @@ -43,6 +39,7 @@ public class ContentLoader{ new Loadouts(), new TechTree(), new Zones(), + new TypeIDs(), //these are not really content classes, but this makes initialization easier new LegacyColorMapper(), @@ -59,8 +56,6 @@ public class ContentLoader{ return; } - registerTypes(); - for(ContentType type : ContentType.values()){ contentMap[type.ordinal()] = new Array<>(); contentNameMap[type.ordinal()] = new ObjectMap<>(); @@ -232,16 +227,4 @@ public class ContentLoader{ public Array units(){ return getBy(ContentType.unit); } - - /** - * Registers sync IDs for all types of sync entities. - * Do not register units here! - */ - private void registerTypes(){ - TypeTrait.registerType(Player.class, Player::new); - TypeTrait.registerType(Fire.class, Fire::new); - TypeTrait.registerType(Puddle.class, Puddle::new); - TypeTrait.registerType(Bullet.class, Bullet::new); - TypeTrait.registerType(Lightning.class, Lightning::new); - } } diff --git a/core/src/io/anuke/mindustry/core/Control.java b/core/src/io/anuke/mindustry/core/Control.java index 6862fb1362..baa5204a34 100644 --- a/core/src/io/anuke/mindustry/core/Control.java +++ b/core/src/io/anuke/mindustry/core/Control.java @@ -1,31 +1,28 @@ package io.anuke.mindustry.core; import io.anuke.arc.*; -import io.anuke.arc.graphics.Color; -import io.anuke.arc.graphics.GL20; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.graphics.g2d.TextureAtlas; -import io.anuke.arc.input.KeyCode; -import io.anuke.arc.scene.ui.Dialog; -import io.anuke.arc.scene.ui.TextField; +import io.anuke.arc.graphics.*; +import io.anuke.arc.graphics.g2d.*; +import io.anuke.arc.input.*; +import io.anuke.arc.scene.ui.*; +import io.anuke.arc.scene.ui.layout.Unit; import io.anuke.arc.util.*; -import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.entities.Effects; -import io.anuke.mindustry.entities.type.Player; +import io.anuke.mindustry.core.GameState.*; +import io.anuke.mindustry.entities.*; +import io.anuke.mindustry.entities.type.*; import io.anuke.mindustry.game.*; import io.anuke.mindustry.game.EventType.*; -import io.anuke.mindustry.gen.Call; +import io.anuke.mindustry.gen.*; import io.anuke.mindustry.input.*; -import io.anuke.mindustry.maps.Map; +import io.anuke.mindustry.maps.*; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.type.*; -import io.anuke.mindustry.ui.dialogs.FloatingDialog; -import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.ui.dialogs.*; +import io.anuke.mindustry.world.*; -import java.io.IOException; -import java.nio.IntBuffer; +import java.io.*; -import static io.anuke.arc.Core.scene; +import static io.anuke.arc.Core.*; import static io.anuke.mindustry.Vars.*; /** @@ -43,19 +40,16 @@ public class Control implements ApplicationListener{ private InputHandler input; public Control(){ - IntBuffer buf = BufferUtils.newIntBuffer(1); - Core.gl.glGetIntegerv(GL20.GL_MAX_TEXTURE_SIZE, buf); - int maxSize = buf.get(0); - + batch = new SpriteBatch(); saves = new Saves(); data = new GlobalData(); + Unit.dp.product = settings.getInt("uiscale", 100) / 100f; + Core.input.setCatch(KeyCode.BACK, true); - Effects.setShakeFalloff(10000f); - content.initialize(Content::init); - Core.atlas = new TextureAtlas(maxSize < 2048 ? "sprites/sprites_fallback.atlas" : "sprites/sprites.atlas"); + Core.atlas = new TextureAtlas("sprites/sprites.atlas"); Draw.scl = 1f / Core.atlas.find("scale_marker").getWidth(); content.initialize(Content::load, true); @@ -122,7 +116,7 @@ public class Control implements ApplicationListener{ Effects.shake(5, 6, Core.camera.position.x, Core.camera.position.y); //the restart dialog can show info for any number of scenarios Call.onGameOver(event.winner); - if(state.rules.zone != null){ + if(state.rules.zone != null && !Net.client()){ //remove zone save on game over if(saves.getZoneSlot() != null){ saves.getZoneSlot().delete(); @@ -213,7 +207,7 @@ public class Control implements ApplicationListener{ ui.loadAnd(() -> { logic.reset(); world.loadGenerator(zone.generator); - state.rules = zone.rules.get(); + zone.rules.accept(state.rules); state.rules.zone = zone; for(Tile core : state.teams.get(defaultTeam).cores){ for(ItemStack stack : zone.getStartingItems()){ @@ -270,6 +264,38 @@ public class Control implements ApplicationListener{ dialog.show(); }); } + + if(Core.settings.getBool("uiscalechanged", false)){ + FloatingDialog dialog = new FloatingDialog("$confirm"); + + float[] countdown = {60 * 11}; + Runnable exit = () -> { + Core.settings.put("uiscale", 100); + Core.settings.put("uiscalechanged", false); + settings.save(); + dialog.hide(); + Core.app.exit(); + }; + + dialog.setFillParent(false); + dialog.cont.label(() -> { + if(countdown[0] <= 0){ + exit.run(); + } + return Core.bundle.format("uiscale.reset", (int)((countdown[0] -= Time.delta()) / 60f)); + }).pad(10f).expand().left(); + + dialog.buttons.defaults().size(200f, 60f); + dialog.buttons.addButton("$uiscale.cancel", exit); + + dialog.buttons.addButton("$ok", () -> { + Core.settings.put("uiscalechanged", false); + settings.save(); + dialog.hide(); + }); + + Core.app.post(dialog::show); + } } @Override @@ -321,7 +347,7 @@ public class Control implements ApplicationListener{ Time.update(); } - if(!scene.hasDialog() && !(scene.root.getChildren().peek() instanceof Dialog) && Core.input.keyTap(KeyCode.BACK)){ + if(!scene.hasDialog() && !scene.root.getChildren().isEmpty() && !(scene.root.getChildren().peek() instanceof Dialog) && Core.input.keyTap(KeyCode.BACK)){ Platform.instance.hide(); } } diff --git a/core/src/io/anuke/mindustry/core/GameState.java b/core/src/io/anuke/mindustry/core/GameState.java index fcf4d6646c..1e755de6c6 100644 --- a/core/src/io/anuke/mindustry/core/GameState.java +++ b/core/src/io/anuke/mindustry/core/GameState.java @@ -2,6 +2,7 @@ package io.anuke.mindustry.core; import io.anuke.arc.Events; import io.anuke.mindustry.entities.type.BaseUnit; +import io.anuke.mindustry.entities.type.base.BaseDrone; import io.anuke.mindustry.game.EventType.StateChangeEvent; import io.anuke.mindustry.game.*; import io.anuke.mindustry.net.Net; @@ -28,7 +29,7 @@ public class GameState{ private State state = State.menu; public int enemies(){ - return Net.client() ? enemies : unitGroups[waveTeam.ordinal()].size(); + return Net.client() ? enemies : unitGroups[waveTeam.ordinal()].count(b -> !(b instanceof BaseDrone)); } public BaseUnit boss(){ diff --git a/core/src/io/anuke/mindustry/core/Logic.java b/core/src/io/anuke/mindustry/core/Logic.java index 1904b713b5..9f6b77ba80 100644 --- a/core/src/io/anuke/mindustry/core/Logic.java +++ b/core/src/io/anuke/mindustry/core/Logic.java @@ -6,17 +6,23 @@ 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.content.Items; +import io.anuke.mindustry.content.*; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.entities.*; import io.anuke.mindustry.entities.type.Player; import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.game.EventType.*; import io.anuke.mindustry.game.*; +import io.anuke.mindustry.game.Teams.TeamData; +import io.anuke.mindustry.gen.BrokenBlock; +import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.type.ItemStack; +import io.anuke.mindustry.world.Block; import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.blocks.BuildBlock; +import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity; import static io.anuke.mindustry.Vars.*; @@ -39,13 +45,25 @@ public class Logic implements ApplicationListener{ p.respawns = state.rules.respawns; } }); - } - @Override - public void init(){ - collisions.setCollider(tilesize, (x, y) -> { - Tile tile = world.tile(x, y); - return tile != null && tile.solid(); + Events.on(BlockDestroyEvent.class, event -> { + //blocks that get broken are appended to the team's broken block queue + Tile tile = event.tile; + Block block = tile.block(); + if(block instanceof BuildBlock){ + BuildEntity entity = tile.entity(); + + //update block to reflect the fact that something was being constructed + if(entity.cblock != null && entity.cblock.synthetic()){ + block = entity.cblock; + }else{ + //otherwise this was a deconstruction that was interrupted, don't want to rebuild that + return; + } + } + + TeamData data = state.teams.get(tile.getTeam()); + data.brokenBlocks.addFirst(BrokenBlock.get(tile.x, tile.y, tile.rotation(), block.id)); }); } @@ -64,9 +82,11 @@ public class Logic implements ApplicationListener{ //add starting items if(!world.isZone()){ for(Team team : Team.all){ - if(state.teams.isActive(team)){ - for(Tile core : state.teams.get(team).cores){ - core.entity.items.add(Items.copper, 200); + if(!state.teams.get(team).cores.isEmpty()){ + TileEntity entity = state.teams.get(team).cores.first().entity; + entity.items.clear(); + for(ItemStack stack : state.rules.loadout){ + entity.items.add(stack.item, stack.amount); } } } @@ -114,8 +134,13 @@ public class Logic implements ApplicationListener{ } if(alive != null && !state.gameOver){ + if(world.isZone() && alive == defaultTeam){ + //in attack maps, a victorious game over is equivalent to a launch + Call.launchZone(); + }else{ + Events.fire(new GameOverEvent(alive)); + } state.gameOver = true; - Events.fire(new GameOverEvent(alive)); } } } @@ -138,6 +163,9 @@ public class Logic implements ApplicationListener{ world.removeBlock(tile); } state.launched = true; + state.gameOver = true; + //manually fire game over event now + Events.fire(new GameOverEvent(defaultTeam)); }); } @@ -181,7 +209,14 @@ public class Logic implements ApplicationListener{ Entities.update(bulletGroup); Entities.update(tileGroup); Entities.update(fireGroup); + }else{ + for(EntityGroup group : unitGroups){ + group.updateEvents(); + collisions.updatePhysics(group); + } } + + Entities.update(playerGroup); //effect group only contains item transfers in the headless version, update it! @@ -197,7 +232,6 @@ public class Logic implements ApplicationListener{ } collisions.collideGroups(bulletGroup, playerGroup); - collisions.collideGroups(playerGroup, playerGroup); } world.pathfinder.update(); diff --git a/core/src/io/anuke/mindustry/core/NetClient.java b/core/src/io/anuke/mindustry/core/NetClient.java index e5395628cc..f873e5d1f5 100644 --- a/core/src/io/anuke/mindustry/core/NetClient.java +++ b/core/src/io/anuke/mindustry/core/NetClient.java @@ -15,8 +15,9 @@ import io.anuke.mindustry.entities.Entities; import io.anuke.mindustry.entities.EntityGroup; import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest; import io.anuke.mindustry.entities.traits.SyncTrait; -import io.anuke.mindustry.entities.traits.TypeTrait; import io.anuke.mindustry.entities.type.Player; +import io.anuke.mindustry.entities.type.Unit; +import io.anuke.mindustry.game.TypeID; import io.anuke.mindustry.game.Version; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.gen.RemoteReadClient; @@ -24,6 +25,7 @@ import io.anuke.mindustry.net.Administration.TraceInfo; import io.anuke.mindustry.net.*; import io.anuke.mindustry.net.Net.SendMode; import io.anuke.mindustry.net.Packets.*; +import io.anuke.mindustry.type.ContentType; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.modules.ItemModule; @@ -229,8 +231,8 @@ public class NetClient implements ApplicationListener{ int id = input.readInt(); byte typeID = input.readByte(); - SyncTrait entity = (SyncTrait)group.getByID(id); - boolean add = false; + SyncTrait entity = group == null ? null : (SyncTrait)group.getByID(id); + boolean add = false, created = false; if(entity == null && id == player.id){ entity = player; @@ -239,16 +241,25 @@ public class NetClient implements ApplicationListener{ //entity must not be added yet, so create it if(entity == null){ - entity = (SyncTrait)TypeTrait.getTypeByID(typeID).get(); //create entity from supplier + entity = (SyncTrait)content.getByID(ContentType.typeid, typeID).constructor.get(); entity.resetID(id); if(!netClient.isEntityUsed(entity.getID())){ add = true; } + created = true; } //read the entity entity.read(input); + if(created && entity.getInterpolator() != null && entity.getInterpolator().target != null){ + //set initial starting position + entity.setNet(entity.getInterpolator().target.x, entity.getInterpolator().target.y); + if(entity instanceof Unit && entity.getInterpolator().targets.length > 0){ + ((Unit)entity).rotation = entity.getInterpolator().targets[0]; + } + } + if(add){ entity.add(); netClient.addRemovedEntity(entity.getID()); @@ -360,11 +371,11 @@ public class NetClient implements ApplicationListener{ if(timer.get(0, playerSyncTime)){ BuildRequest[] requests; //limit to 10 to prevent buffer overflows - int usedRequests = Math.min(player.getPlaceQueue().size, 10); + int usedRequests = Math.min(player.buildQueue().size, 10); requests = new BuildRequest[usedRequests]; for(int i = 0; i < usedRequests; i++){ - requests[i] = player.getPlaceQueue().get(i); + requests[i] = player.buildQueue().get(i); } Call.onClientShapshot(lastSent++, player.x, player.y, diff --git a/core/src/io/anuke/mindustry/core/NetServer.java b/core/src/io/anuke/mindustry/core/NetServer.java index dbc09ca4c4..b9c8510b02 100644 --- a/core/src/io/anuke/mindustry/core/NetServer.java +++ b/core/src/io/anuke/mindustry/core/NetServer.java @@ -40,7 +40,7 @@ import static io.anuke.mindustry.Vars.*; public class NetServer implements ApplicationListener{ public final static int maxSnapshotSize = 430; - private final static float serverSyncTime = 20, kickDuration = 30 * 1000; + private final static float serverSyncTime = 15, kickDuration = 30 * 1000; private final static Vector2 vector = new Vector2(); private final static Rectangle viewport = new Rectangle(); /** If a player goes away of their server-side coordinates by this distance, they get teleported back. */ @@ -274,7 +274,7 @@ public class NetServer implements ApplicationListener{ long elapsed = Time.timeSinceMillis(connection.lastRecievedClientTime); float maxSpeed = boosting && !player.mech.flying ? player.mech.boostSpeed : player.mech.speed; - float maxMove = elapsed / 1000f * 60f * Math.min(compound(maxSpeed, player.mech.drag) * 1.25f, player.mech.maxSpeed * 1.1f); + float maxMove = elapsed / 1000f * 60f * Math.min(compound(maxSpeed, player.mech.drag) * 1.25f, player.mech.maxSpeed * 1.2f); player.pointerX = pointerX; player.pointerY = pointerY; @@ -282,8 +282,9 @@ public class NetServer implements ApplicationListener{ player.isTyping = chatting; player.isBoosting = boosting; player.isShooting = shooting; - player.getPlaceQueue().clear(); + player.buildQueue().clear(); for(BuildRequest req : requests){ + if(req == null) continue; Tile tile = world.tile(req.x, req.y); if(tile == null) continue; //auto-skip done requests @@ -292,11 +293,11 @@ public class NetServer implements ApplicationListener{ }else if(!req.breaking && tile.block() == req.block && (!req.block.rotate || tile.rotation() == req.rotation)){ continue; } - player.getPlaceQueue().addLast(req); + player.buildQueue().addLast(req); } vector.set(x - player.getInterpolator().target.x, y - player.getInterpolator().target.y); - //vector.limit(maxMove); + vector.limit(maxMove); float prevx = player.x, prevy = player.y; player.set(player.getInterpolator().target.x, player.getInterpolator().target.y); @@ -473,7 +474,7 @@ public class NetServer implements ApplicationListener{ //write all entities now dataStream.writeInt(entity.getID()); //write id - dataStream.writeByte(sync.getTypeID()); //write type ID + dataStream.writeByte(sync.getTypeID().id); //write type ID sync.write(dataStream); //write entity sent++; diff --git a/core/src/io/anuke/mindustry/core/Renderer.java b/core/src/io/anuke/mindustry/core/Renderer.java index a6a5aa1363..1fd54ee86d 100644 --- a/core/src/io/anuke/mindustry/core/Renderer.java +++ b/core/src/io/anuke/mindustry/core/Renderer.java @@ -1,7 +1,6 @@ package io.anuke.mindustry.core; -import io.anuke.arc.ApplicationListener; -import io.anuke.arc.Core; +import io.anuke.arc.*; import io.anuke.arc.files.FileHandle; import io.anuke.arc.function.Consumer; import io.anuke.arc.function.Predicate; @@ -21,6 +20,7 @@ import io.anuke.mindustry.entities.effect.GroundEffectEntity.GroundEffect; import io.anuke.mindustry.entities.impl.EffectEntity; import io.anuke.mindustry.entities.traits.*; import io.anuke.mindustry.entities.type.*; +import io.anuke.mindustry.game.EventType.DisposeEvent; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.graphics.*; import io.anuke.mindustry.world.blocks.defense.ForceProjector.ShieldEntity; @@ -35,6 +35,7 @@ public class Renderer implements ApplicationListener{ public final Pixelator pixelator = new Pixelator(); public FrameBuffer shieldBuffer = new FrameBuffer(2, 2); + private Bloom bloom; private Color clearColor; private float targetscale = io.anuke.arc.scene.ui.layout.Unit.dp.scl(4); private float camerascale = targetscale; @@ -42,8 +43,10 @@ public class Renderer implements ApplicationListener{ private float shakeIntensity, shaketime; public Renderer(){ - batch = new SpriteBatch(4096); camera = new Camera(); + if(settings.getBool("bloom")){ + setupBloom(); + } Lines.setCircleVertices(20); Shaders.init(); @@ -113,7 +116,7 @@ public class Renderer implements ApplicationListener{ }else{ camera.position.lerpDelta(position, 0.08f); } - }else if(!mobile){ + }else if(!mobile || settings.getBool("keyboard")){ camera.position.lerpDelta(position, 0.08f); } @@ -131,6 +134,46 @@ public class Renderer implements ApplicationListener{ minimap.dispose(); shieldBuffer.dispose(); blocks.dispose(); + if(bloom != null){ + bloom.dispose(); + bloom = null; + } + Events.fire(new DisposeEvent()); + } + + @Override + public void resize(int width, int height){ + if(settings.getBool("bloom")){ + setupBloom(); + } + } + + void setupBloom(){ + try{ + if(bloom != null){ + bloom.dispose(); + } + bloom = new Bloom(true); + bloom.setClearColor(0f, 0f, 0f, 0f); + }catch(Exception e){ + e.printStackTrace(); + settings.put("bloom", false); + settings.save(); + ui.showError("$error.bloom"); + } + } + + public void toggleBloom(boolean enabled){ + if(enabled){ + if(bloom == null){ + setupBloom(); + } + }else{ + if(bloom != null){ + bloom.dispose(); + bloom = null; + } + } } void updateShake(float scale){ @@ -163,9 +206,9 @@ public class Renderer implements ApplicationListener{ blocks.floor.drawFloor(); - drawAndInterpolate(groundEffectGroup, e -> e instanceof BelowLiquidTrait); - drawAndInterpolate(puddleGroup); - drawAndInterpolate(groundEffectGroup, e -> !(e instanceof BelowLiquidTrait)); + draw(groundEffectGroup, e -> e instanceof BelowLiquidTrait); + draw(puddleGroup); + draw(groundEffectGroup, e -> !(e instanceof BelowLiquidTrait)); blocks.processBlocks(); @@ -189,18 +232,29 @@ public class Renderer implements ApplicationListener{ drawAllTeams(false); - blocks.skipLayer(Layer.turret); - blocks.drawBlocks(Layer.laser); + blocks.drawBlocks(Layer.turret); drawFlyerShadows(); + blocks.drawBlocks(Layer.power); + drawAllTeams(true); - drawAndInterpolate(bulletGroup); - drawAndInterpolate(effectGroup); + Draw.flush(); + if(bloom != null && !pixelator.enabled()){ + bloom.capture(); + } + + draw(bulletGroup); + draw(effectGroup); + + Draw.flush(); + if(bloom != null && !pixelator.enabled()){ + bloom.render(); + } overlays.drawBottom(); - drawAndInterpolate(playerGroup, p -> true, Player::drawBuildRequests); + draw(playerGroup, p -> true, Player::drawBuildRequests); if(Entities.countInBounds(shieldGroup) > 0){ if(settings.getBool("animatedshields")){ @@ -223,7 +277,7 @@ public class Renderer implements ApplicationListener{ overlays.drawTop(); - drawAndInterpolate(playerGroup, p -> !p.isDead() && !p.isLocal, Player::drawName); + draw(playerGroup, p -> !p.isDead() && !p.isLocal, Player::drawName); Draw.color(); Draw.flush(); @@ -240,12 +294,12 @@ public class Renderer implements ApplicationListener{ for(EntityGroup group : unitGroups){ if(!group.isEmpty()){ - drawAndInterpolate(group, unit -> !unit.isDead(), draw::accept); + draw(group, unit -> !unit.isDead(), draw::accept); } } if(!playerGroup.isEmpty()){ - drawAndInterpolate(playerGroup, unit -> !unit.isDead(), draw::accept); + draw(playerGroup, unit -> !unit.isDead(), draw::accept); } Draw.color(); @@ -257,12 +311,12 @@ public class Renderer implements ApplicationListener{ for(EntityGroup group : unitGroups){ if(!group.isEmpty()){ - drawAndInterpolate(group, unit -> unit.isFlying() && !unit.isDead(), baseUnit -> baseUnit.drawShadow(trnsX, trnsY)); + draw(group, unit -> unit.isFlying() && !unit.isDead(), baseUnit -> baseUnit.drawShadow(trnsX, trnsY)); } } if(!playerGroup.isEmpty()){ - drawAndInterpolate(playerGroup, unit -> unit.isFlying() && !unit.isDead(), player -> player.drawShadow(trnsX, trnsY)); + draw(playerGroup, unit -> unit.isFlying() && !unit.isDead(), player -> player.drawShadow(trnsX, trnsY)); } Draw.color(); @@ -275,27 +329,26 @@ public class Renderer implements ApplicationListener{ if(group.count(p -> p.isFlying() == flying) + playerGroup.count(p -> p.isFlying() == flying && p.getTeam() == team) == 0 && flying) continue; - drawAndInterpolate(unitGroups[team.ordinal()], u -> u.isFlying() == flying && !u.isDead(), Unit::drawUnder); - drawAndInterpolate(playerGroup, p -> p.isFlying() == flying && p.getTeam() == team && !p.isDead(), Unit::drawUnder); + draw(unitGroups[team.ordinal()], u -> u.isFlying() == flying && !u.isDead(), Unit::drawUnder); + draw(playerGroup, p -> p.isFlying() == flying && p.getTeam() == team && !p.isDead(), Unit::drawUnder); - drawAndInterpolate(unitGroups[team.ordinal()], u -> u.isFlying() == flying && !u.isDead(), Unit::drawAll); - drawAndInterpolate(playerGroup, p -> p.isFlying() == flying && p.getTeam() == team, Unit::drawAll); - blocks.drawTeamBlocks(Layer.turret, team); + draw(unitGroups[team.ordinal()], u -> u.isFlying() == flying && !u.isDead(), Unit::drawAll); + draw(playerGroup, p -> p.isFlying() == flying && p.getTeam() == team, Unit::drawAll); - drawAndInterpolate(unitGroups[team.ordinal()], u -> u.isFlying() == flying && !u.isDead(), Unit::drawOver); - drawAndInterpolate(playerGroup, p -> p.isFlying() == flying && p.getTeam() == team, Unit::drawOver); + draw(unitGroups[team.ordinal()], u -> u.isFlying() == flying && !u.isDead(), Unit::drawOver); + draw(playerGroup, p -> p.isFlying() == flying && p.getTeam() == team, Unit::drawOver); } } - public void drawAndInterpolate(EntityGroup group){ - drawAndInterpolate(group, t -> true, DrawTrait::draw); + public void draw(EntityGroup group){ + draw(group, t -> true, DrawTrait::draw); } - public void drawAndInterpolate(EntityGroup group, Predicate toDraw){ - drawAndInterpolate(group, toDraw, DrawTrait::draw); + public void draw(EntityGroup group, Predicate toDraw){ + draw(group, toDraw, DrawTrait::draw); } - public void drawAndInterpolate(EntityGroup group, Predicate toDraw, Consumer drawer){ + public void draw(EntityGroup group, Predicate toDraw, Consumer drawer){ Entities.draw(group, toDraw, drawer); } diff --git a/core/src/io/anuke/mindustry/core/UI.java b/core/src/io/anuke/mindustry/core/UI.java index ef57acaa8b..8701bcfda5 100644 --- a/core/src/io/anuke/mindustry/core/UI.java +++ b/core/src/io/anuke/mindustry/core/UI.java @@ -1,30 +1,32 @@ package io.anuke.mindustry.core; import io.anuke.arc.*; -import io.anuke.arc.Graphics.Cursor; -import io.anuke.arc.Graphics.Cursor.SystemCursor; -import io.anuke.arc.freetype.FreeTypeFontGenerator; -import io.anuke.arc.freetype.FreeTypeFontGenerator.FreeTypeFontParameter; -import io.anuke.arc.function.Consumer; -import io.anuke.arc.graphics.Color; -import io.anuke.arc.graphics.Colors; -import io.anuke.arc.graphics.g2d.BitmapFont; -import io.anuke.arc.input.KeyCode; -import io.anuke.arc.math.Interpolation; +import io.anuke.arc.Graphics.*; +import io.anuke.arc.Graphics.Cursor.*; +import io.anuke.arc.freetype.*; +import io.anuke.arc.freetype.FreeTypeFontGenerator.*; +import io.anuke.arc.function.*; +import io.anuke.arc.graphics.*; +import io.anuke.arc.graphics.g2d.*; +import io.anuke.arc.graphics.g2d.TextureAtlas.*; +import io.anuke.arc.input.*; +import io.anuke.arc.math.*; import io.anuke.arc.scene.*; -import io.anuke.arc.scene.actions.Actions; +import io.anuke.arc.scene.actions.*; +import io.anuke.arc.scene.event.*; +import io.anuke.arc.scene.style.*; import io.anuke.arc.scene.ui.*; -import io.anuke.arc.scene.ui.TextField.TextFieldFilter; -import io.anuke.arc.scene.ui.layout.Table; -import io.anuke.arc.scene.ui.layout.Unit; +import io.anuke.arc.scene.ui.TextField.*; +import io.anuke.arc.scene.ui.Tooltip.*; +import io.anuke.arc.scene.ui.layout.*; import io.anuke.arc.util.*; -import io.anuke.mindustry.editor.MapEditorDialog; -import io.anuke.mindustry.game.EventType.ResizeEvent; -import io.anuke.mindustry.graphics.Pal; +import io.anuke.mindustry.core.GameState.*; +import io.anuke.mindustry.editor.*; +import io.anuke.mindustry.game.EventType.*; +import io.anuke.mindustry.graphics.*; import io.anuke.mindustry.ui.dialogs.*; import io.anuke.mindustry.ui.fragments.*; -import static io.anuke.arc.scene.actions.Actions.*; import static io.anuke.mindustry.Vars.*; public class UI implements ApplicationListener{ @@ -34,9 +36,10 @@ public class UI implements ApplicationListener{ public HudFragment hudfrag; public ChatFragment chatfrag; public PlayerListFragment listfrag; - public BackgroundFragment backfrag; public LoadingFragment loadfrag; + public WidgetGroup menuGroup, hudGroup; + public AboutDialog about; public GameOverDialog restart; public CustomGameDialog custom; @@ -53,7 +56,6 @@ public class UI implements ApplicationListener{ public BansDialog bans; public AdminsDialog admins; public TraceDialog traces; - public ChangelogDialog changelog; public DatabaseDialog database; public ContentInfoDialog content; public DeployDialog deploy; @@ -65,6 +67,7 @@ public class UI implements ApplicationListener{ public UI(){ Skin skin = new Skin(Core.atlas); generateFonts(skin); + loadExtraStyle(skin); skin.load(Core.files.internal("sprites/uiskin.json")); for(BitmapFont font : skin.getAll(BitmapFont.class).values()){ @@ -74,25 +77,13 @@ public class UI implements ApplicationListener{ Core.scene = new Scene(skin); Core.input.addProcessor(Core.scene); - Dialog.setShowAction(() -> sequence( - alpha(0f), - originCenter(), - moveToAligned(Core.graphics.getWidth() / 2f, Core.graphics.getHeight() / 2f, Align.center), - scaleTo(0.0f, 1f), - parallel( - scaleTo(1f, 1f, 0.1f, Interpolation.fade), - fadeIn(0.1f, Interpolation.fade) - ) - )); + //Dialog.setShowAction(() -> sequence(translateTo(Core.graphics.getWidth(), 0f), translateBy(-Core.graphics.getWidth(), 0f, 0.1f, Interpolation.fade))); + //Dialog.setHideAction(() -> sequence(translateBy(-Core.graphics.getWidth(), 0f, 0.1f, Interpolation.fade))); - Dialog.setHideAction(() -> sequence( - parallel( - scaleTo(0.01f, 0.01f, 0.1f, Interpolation.fade), - fadeOut(0.1f, Interpolation.fade) - ) - )); + Dialog.setShowAction(Actions::sequence); + Dialog.setHideAction(Actions::sequence); - TooltipManager.getInstance().animations = false; + Tooltips.getInstance().animations = false; Core.settings.setErrorHandler(e -> { e.printStackTrace(); @@ -100,11 +91,31 @@ public class UI implements ApplicationListener{ }); Colors.put("accent", Pal.accent); + Colors.put("highlight", Pal.accent.cpy().lerp(Color.WHITE, 0.3f)); Colors.put("stat", Pal.stat); loadCursors(); } + void loadExtraStyle(Skin skin){ + AtlasRegion region = Core.atlas.find("flat-down-base"); + int[] splits = region.splits; + + ScaledNinePatchDrawable copy = new ScaledNinePatchDrawable(new NinePatch(region, splits[0], splits[1], splits[2], splits[3])){ + public float getLeftWidth(){ return 0; } + public float getRightWidth(){ return 0; } + public float getTopHeight(){ return 0; } + public float getBottomHeight(){ return 0; } + }; + copy.setMinWidth(0); + copy.setMinHeight(0); + copy.setTopHeight(0); + copy.setRightWidth(0); + copy.setBottomHeight(0); + copy.setLeftWidth(0); + skin.add("flat-down", copy, Drawable.class); + } + void loadCursors(){ int cursorScaling = 1, outlineThickness = 3; Color outlineColor = Color.valueOf("444444"); @@ -142,11 +153,13 @@ public class UI implements ApplicationListener{ @Override public void init(){ + menuGroup = new WidgetGroup(); + hudGroup = new WidgetGroup(); + menufrag = new MenuFragment(); hudfrag = new HudFragment(); chatfrag = new ChatFragment(); listfrag = new PlayerListFragment(); - backfrag = new BackgroundFragment(); loadfrag = new LoadingFragment(); editor = new MapEditorDialog(); @@ -161,7 +174,6 @@ public class UI implements ApplicationListener{ settings = new SettingsMenuDialog(); host = new HostDialog(); paused = new PausedDialog(); - changelog = new ChangelogDialog(); about = new AboutDialog(); bans = new BansDialog(); admins = new AdminsDialog(); @@ -174,12 +186,21 @@ public class UI implements ApplicationListener{ Group group = Core.scene.root; - backfrag.build(group); - control.input().getFrag().build(group); - hudfrag.build(group); - menufrag.build(group); - chatfrag.container().build(group); - listfrag.build(group); + menuGroup.setFillParent(true); + menuGroup.touchable(Touchable.childrenOnly); + menuGroup.visible(() -> state.is(State.menu)); + hudGroup.setFillParent(true); + hudGroup.touchable(Touchable.childrenOnly); + hudGroup.visible(() -> !state.is(State.menu)); + + Core.scene.add(menuGroup); + Core.scene.add(hudGroup); + + control.input().getFrag().build(hudGroup); + hudfrag.build(hudGroup); + menufrag.build(menuGroup); + chatfrag.container().build(hudGroup); + listfrag.build(hudGroup); loadfrag.build(group); } @@ -206,12 +227,12 @@ public class UI implements ApplicationListener{ }); } - public void showTextInput(String titleText, String text, String def, TextFieldFilter filter, Consumer confirmed){ + public void showTextInput(String titleText, String text, int textLength, String def, TextFieldFilter filter, Consumer confirmed){ new Dialog(titleText, "dialog"){{ cont.margin(30).add(text).padRight(6f); TextField field = cont.addField(def, t -> { }).size(170f, 50f).get(); - field.setFilter((f, c) -> field.getText().length() < 12 && filter.acceptChar(f, c)); + field.setFilter((f, c) -> field.getText().length() < textLength && filter.acceptChar(f, c)); Platform.instance.addDialog(field); buttons.defaults().size(120, 54).pad(4); buttons.addButton("$ok", () -> { @@ -223,7 +244,11 @@ public class UI implements ApplicationListener{ } public void showTextInput(String title, String text, String def, Consumer confirmed){ - showTextInput(title, text, def, (field, c) -> true, confirmed); + showTextInput(title, text, 12, def, (field, c) -> true, confirmed); + } + + public void showTextInput(String title, String text, int textLength, String def, Consumer confirmed){ + showTextInput(title, text, textLength < 0 ? 12 : textLength, def, (field, c) -> true, confirmed); } public void showInfoFade(String info){ diff --git a/core/src/io/anuke/mindustry/core/World.java b/core/src/io/anuke/mindustry/core/World.java index 90762e9997..59cda8703f 100644 --- a/core/src/io/anuke/mindustry/core/World.java +++ b/core/src/io/anuke/mindustry/core/World.java @@ -1,25 +1,25 @@ package io.anuke.mindustry.core; -import io.anuke.annotations.Annotations.Nullable; +import io.anuke.annotations.Annotations.*; import io.anuke.arc.*; -import io.anuke.arc.collection.IntArray; -import io.anuke.arc.math.Mathf; -import io.anuke.arc.math.geom.Geometry; -import io.anuke.arc.math.geom.Point2; +import io.anuke.arc.collection.*; +import io.anuke.arc.math.*; +import io.anuke.arc.math.geom.*; import io.anuke.arc.util.*; import io.anuke.mindustry.ai.*; -import io.anuke.mindustry.content.Blocks; -import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.entities.Entities; -import io.anuke.mindustry.game.EventType.TileChangeEvent; -import io.anuke.mindustry.game.EventType.WorldLoadEvent; -import io.anuke.mindustry.game.Team; -import io.anuke.mindustry.io.MapIO; +import io.anuke.mindustry.content.*; +import io.anuke.mindustry.core.GameState.*; +import io.anuke.mindustry.entities.*; +import io.anuke.mindustry.game.EventType.*; +import io.anuke.mindustry.game.*; +import io.anuke.mindustry.io.*; import io.anuke.mindustry.maps.*; -import io.anuke.mindustry.maps.generators.Generator; -import io.anuke.mindustry.type.Zone; +import io.anuke.mindustry.maps.filters.*; +import io.anuke.mindustry.maps.filters.GenerateFilter.*; +import io.anuke.mindustry.maps.generators.*; +import io.anuke.mindustry.type.*; import io.anuke.mindustry.world.*; -import io.anuke.mindustry.world.blocks.BlockPart; +import io.anuke.mindustry.world.blocks.*; import static io.anuke.mindustry.Vars.*; @@ -90,6 +90,14 @@ public class World implements ApplicationListener{ return tiles == null ? 0 : tiles[0].length; } + public int unitWidth(){ + return width()*tilesize; + } + + public int unitHeight(){ + return height()*tilesize; + } + public @Nullable Tile tile(int pos){ return tiles == null ? null : tile(Pos.x(pos), Pos.y(pos)); } @@ -164,12 +172,6 @@ public class World implements ApplicationListener{ generating = true; } - /** Call to signal the beginning of loading the map with a custom set of tiles. */ - public void beginMapLoad(Tile[][] tiles){ - this.tiles = tiles; - generating = true; - } - /** * Call to signify the end of map loading. Updates tile occlusions and sets up physics for the world. * A WorldLoadEvent will be fire. @@ -218,9 +220,8 @@ public class World implements ApplicationListener{ } public void loadMap(Map map){ - try{ - MapIO.loadMap(map); + SaveIO.load(map.file, new FilterContext(map)); }catch(Exception e){ Log.err(e); if(!headless){ @@ -237,13 +238,13 @@ public class World implements ApplicationListener{ invalidMap = false; if(!headless){ - if(state.teams.get(player.getTeam()).cores.size == 0){ + if(state.teams.get(defaultTeam).cores.size == 0){ ui.showError("$map.nospawn"); invalidMap = true; }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 != player.getTeam()){ + if(state.teams.get(team).cores.size != 0 && team != defaultTeam){ invalidMap = false; } } @@ -307,50 +308,6 @@ public class World implements ApplicationListener{ } } - /** - * Raycast, but with world coordinates. - */ - public Point2 raycastWorld(float x, float y, float x2, float y2){ - return raycast(Math.round(x / tilesize), Math.round(y / tilesize), - Math.round(x2 / tilesize), Math.round(y2 / tilesize)); - } - - /** - * Input is in block coordinates, not world coordinates. - * @return null if no collisions found, block position otherwise. - */ - public Point2 raycast(int x0f, int y0f, int x1, int y1){ - int x0 = x0f; - int y0 = y0f; - int dx = Math.abs(x1 - x0); - int dy = Math.abs(y1 - y0); - - int sx = x0 < x1 ? 1 : -1; - int sy = y0 < y1 ? 1 : -1; - - int err = dx - dy; - int e2; - while(true){ - - if(!passable(x0, y0)){ - return Tmp.g1.set(x0, y0); - } - if(x0 == x1 && y0 == y1) break; - - e2 = 2 * err; - if(e2 > -dy){ - err = err - dy; - x0 = x0 + sx; - } - - if(e2 < dx){ - err = err + dx; - y0 = y0 + sy; - } - } - return null; - } - public void raycastEachWorld(float x0, float y0, float x1, float y1, Raycaster cons){ raycastEach(toTile(x0), toTile(y0), toTile(x1), toTile(y1), cons); } @@ -481,7 +438,7 @@ public class World implements ApplicationListener{ boolean accept(int x, int y); } - class Context implements WorldContext{ + private class Context implements WorldContext{ @Override public Tile tile(int x, int y){ return tiles[x][y]; @@ -512,4 +469,44 @@ public class World implements ApplicationListener{ endMapLoad(); } } + + /** World context that applies filters after generation end. */ + private class FilterContext extends Context{ + final Map map; + + FilterContext(Map map){ + this.map = map; + } + + @Override + public void end(){ + Array filters = map.filters(); + if(!filters.isEmpty()){ + //input for filter queries + GenerateInput input = new GenerateInput(); + + for(GenerateFilter filter : filters){ + input.begin(filter, width(), height(), (x, y) -> tiles[x][y]); + + //actually apply the filter + for(int x = 0; x < width(); x++){ + for(int y = 0; y < height(); y++){ + Tile tile = rawTile(x, y); + input.apply(x, y, tile.floor(), tile.block(), tile.overlay()); + filter.apply(input); + + tile.setFloor((Floor)input.floor); + tile.setOverlay(input.ore); + + if(!tile.block().synthetic() && !input.block.synthetic()){ + tile.setBlock(input.block); + } + } + } + } + } + + super.end(); + } + } } diff --git a/core/src/io/anuke/mindustry/editor/DrawOperation.java b/core/src/io/anuke/mindustry/editor/DrawOperation.java index adf2551079..b5a81a759f 100755 --- a/core/src/io/anuke/mindustry/editor/DrawOperation.java +++ b/core/src/io/anuke/mindustry/editor/DrawOperation.java @@ -9,7 +9,6 @@ import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.blocks.Floor; import static io.anuke.mindustry.Vars.content; -import static io.anuke.mindustry.Vars.world; public class DrawOperation{ private MapEditor editor; @@ -66,7 +65,7 @@ public class DrawOperation{ tile.setFloor((Floor)content.block(to)); }else if(type == OpType.block.ordinal()){ Block block = content.block(to); - world.setBlock(tile, block, tile.getTeam(), tile.rotation()); + tile.setBlock(block, tile.getTeam(), tile.rotation()); }else if(type == OpType.rotation.ordinal()){ tile.rotation(to); }else if(type == OpType.team.ordinal()){ diff --git a/core/src/io/anuke/mindustry/editor/EditorTile.java b/core/src/io/anuke/mindustry/editor/EditorTile.java index 41234e1578..0e6f0d28f3 100644 --- a/core/src/io/anuke/mindustry/editor/EditorTile.java +++ b/core/src/io/anuke/mindustry/editor/EditorTile.java @@ -91,6 +91,11 @@ public class EditorTile extends Tile{ super.rotation(rotation); } + @Override + public void setOverlay(Block overlay){ + setOverlayID(overlay.id); + } + @Override public void setOverlayID(short overlay){ if(state.is(State.playing)){ @@ -99,7 +104,7 @@ public class EditorTile extends Tile{ } if(overlayID() == overlay) return; - op(OpType.overlay, this.overlay); + op(OpType.overlay, this.overlay.id); super.setOverlayID(overlay); } diff --git a/core/src/io/anuke/mindustry/editor/EditorTool.java b/core/src/io/anuke/mindustry/editor/EditorTool.java index 7eb6ffa334..9da41ad7f2 100644 --- a/core/src/io/anuke/mindustry/editor/EditorTool.java +++ b/core/src/io/anuke/mindustry/editor/EditorTool.java @@ -1,13 +1,15 @@ package io.anuke.mindustry.editor; -import io.anuke.arc.Core; import io.anuke.arc.collection.IntArray; -import io.anuke.arc.function.IntPositionConsumer; -import io.anuke.arc.input.KeyCode; -import io.anuke.arc.util.*; +import io.anuke.arc.function.*; +import io.anuke.arc.math.Mathf; +import io.anuke.arc.math.geom.Bresenham2; +import io.anuke.arc.util.Structs; +import io.anuke.mindustry.Vars; import io.anuke.mindustry.content.Blocks; +import io.anuke.mindustry.game.Team; import io.anuke.mindustry.world.*; -import io.anuke.mindustry.world.blocks.*; +import io.anuke.mindustry.world.blocks.BlockPart; public enum EditorTool{ zoom, @@ -16,12 +18,34 @@ public enum EditorTool{ if(!Structs.inBounds(x, y, editor.width(), editor.height())) return; Tile tile = editor.tile(x, y).link(); - editor.drawBlock = tile.block() == Blocks.air ? tile.overlay() == Blocks.air ? tile.floor() : tile.overlay() : tile.block(); } }, - line, - pencil{ + line("replace", "orthogonal"){ + + @Override + public void touchedLine(MapEditor editor, int x1, int y1, int x2, int y2){ + //straight + if(mode == 1){ + if(Math.abs(x2 - x1) > Math.abs(y2 - y1)){ + y2 = y1; + }else{ + x2 = x1; + } + } + + Bresenham2.line(x1, y1, x2, y2, (x, y) -> { + if(mode == 0){ + //replace + editor.drawBlocksReplace(x, y); + }else{ + //normal + editor.drawBlocks(x, y); + } + }); + } + }, + pencil("replace", "square", "drawteams"){ { edit = true; draggable = true; @@ -29,10 +53,23 @@ public enum EditorTool{ @Override public void touched(MapEditor editor, int x, int y){ - editor.draw(x, y, isPaint()); + if(mode == -1){ + //normal mode + editor.drawBlocks(x, y); + }else if(mode == 0){ + //replace mode + editor.drawBlocksReplace(x, y); + }else if(mode == 1){ + //square mode + editor.drawBlocks(x, y, true, tile -> true); + }else if(mode == 2){ + //draw teams + editor.drawCircle(x, y, tile -> tile.link().setTeam(editor.drawTeam)); + } + } }, - eraser{ + eraser("eraseores"){ { edit = true; draggable = true; @@ -40,19 +77,25 @@ public enum EditorTool{ @Override public void touched(MapEditor editor, int x, int y){ - editor.draw(x, y, isPaint(), Blocks.air); + editor.drawCircle(x, y, tile -> { + if(mode == -1){ + //erase block + Vars.world.removeBlock(tile); + }else if(mode == 0){ + //erase ore + tile.clearOverlay(); + } + }); } }, - fill{ + fill("replaceall", "fillteams"){ { edit = true; } IntArray stack = new IntArray(); - Block dest; - boolean isFloor; - MapEditor data; + @Override public void touched(MapEditor editor, int x, int y){ if(!Structs.inBounds(x, y, editor.width(), editor.height())) return; Tile tile = editor.tile(x, y); @@ -63,74 +106,65 @@ public enum EditorTool{ return; } - data = editor; - isFloor = editor.drawBlock instanceof Floor; + //mode 0 or 1, fill everything with the floor/tile or replace it + if(mode == 0 || mode == -1){ + //can't fill parts or multiblocks + if(tile.block() instanceof BlockPart || tile.block().isMultiblock()){ + return; + } - Block floor = tile.floor(); - Block block = tile.block(); - boolean synth = editor.drawBlock.synthetic(); + Predicate tester; + Consumer setter; - Block draw = editor.drawBlock; - dest = draw instanceof OverlayFloor ? tile.overlay() : isFloor ? floor : block; - - if(dest == draw || block instanceof BlockPart || block.isMultiblock()){ - return; - } - - boolean alt = isAlt(); - - int width = editor.width(); - int height = editor.height(); - - IntPositionConsumer writer = (px, py) -> { - Tile write = editor.tile(px, py); - - if(isFloor){ - if(alt && !(draw instanceof OverlayFloor)){ - Block ore = write.overlay(); - write.setFloor((Floor)draw); - write.setOverlay(ore); - }else{ - write.setFloor((Floor)draw); - } + if(editor.drawBlock.isOverlay()){ + Block dest = tile.overlay(); + if(dest == editor.drawBlock) return; + tester = t -> t.overlay() == dest; + setter = t -> t.setOverlay(editor.drawBlock); + }else if(editor.drawBlock.isFloor()){ + Block dest = tile.floor(); + if(dest == editor.drawBlock) return; + tester = t -> t.floor() == dest; + setter = t -> t.setFloorUnder(editor.drawBlock.asFloor()); }else{ - write.setBlock(draw); + Block dest = tile.block(); + if(dest == editor.drawBlock) return; + tester = t -> t.block() == dest; + setter = t -> t.setBlock(editor.drawBlock, editor.drawTeam); } - if(synth){ - write.setTeam(editor.drawTeam); - } + //replace only when the mode is 0 using the specified functions + fill(editor, x, y, mode == 0, tester, setter); + }else if(mode == 1){ //mode 1 is team fill - if(draw.rotate){ - write.rotation((byte)editor.rotation); + //only fill synthetic blocks, it's meaningless otherwise + if(tile.link().synthetic()){ + Team dest = tile.getTeam(); + if(dest == editor.drawTeam) return; + fill(editor, x, y, false, t -> t.getTeamID() == dest.ordinal() && t.link().synthetic(), t -> t.setTeam(editor.drawTeam)); } - }; + } + } - if(isAlt()){ - //fill all of the same type regardless of borders + void fill(MapEditor editor, int x, int y, boolean replace, Predicate tester, Consumer filler){ + int width = editor.width(), height = editor.height(); + + if(replace){ + //just do it on everything for(int cx = 0; cx < width; cx++){ for(int cy = 0; cy < height; cy++){ - if(eq(cx, cy)){ - writer.accept(cx, cy); - } - } - } - }else if(isAlt2()){ - //fill all teams. - for(int cx = 0; cx < width; cx++){ - for(int cy = 0; cy < height; cy++){ - Tile write = editor.tile(cx, cy); - if(write.block().synthetic()){ - write.setTeam(editor.drawTeam); + Tile tile = editor.tile(cx, cy); + if(tester.test(tile)){ + filler.accept(tile); } } } + }else{ - //normal fill + //perform flood fill int x1; stack.clear(); - stack.add(Pos.get(x, y)); while(stack.size > 0){ @@ -139,23 +173,23 @@ public enum EditorTool{ y = Pos.y(popped); x1 = x; - while(x1 >= 0 && eq(x1, y)) x1--; + while(x1 >= 0 && tester.test(editor.tile(x1, y))) x1--; x1++; boolean spanAbove = false, spanBelow = false; - while(x1 < width && eq(x1, y)){ - writer.accept(x1, y); + while(x1 < width && tester.test(editor.tile(x1, y))){ + filler.accept(editor.tile(x1, y)); - if(!spanAbove && y > 0 && eq(x1, y - 1)){ + if(!spanAbove && y > 0 && tester.test(editor.tile(x1, y - 1))){ stack.add(Pos.get(x1, y - 1)); spanAbove = true; - }else if(spanAbove && !eq(x1, y - 1)){ + }else if(spanAbove && !tester.test(editor.tile(x1, y - 1))){ spanAbove = false; } - if(!spanBelow && y < height - 1 && eq(x1, y + 1)){ + if(!spanBelow && y < height - 1 && tester.test(editor.tile(x1, y + 1))){ stack.add(Pos.get(x1, y + 1)); spanBelow = true; - }else if(spanBelow && y < height - 1 && !eq(x1, y + 1)){ + }else if(spanBelow && y < height - 1 && !tester.test(editor.tile(x1, y + 1))){ spanBelow = false; } x1++; @@ -163,14 +197,10 @@ public enum EditorTool{ } } } - - boolean eq(int px, int py){ - Tile tile = data.tile(px, py); - - return (data.drawBlock instanceof OverlayFloor ? tile.overlay() : isFloor ? tile.floor() : tile.block()) == dest && !(data.drawBlock instanceof OverlayFloor && tile.floor().isLiquid); - } }, - spray{ + spray("replace"){ + final double chance = 0.012; + { edit = true; draggable = true; @@ -178,25 +208,40 @@ public enum EditorTool{ @Override public void touched(MapEditor editor, int x, int y){ - editor.draw(x, y, isPaint(), editor.drawBlock, 0.012); + + //floor spray + if(editor.drawBlock.isFloor()){ + editor.drawCircle(x, y, tile -> { + if(Mathf.chance(chance)){ + tile.setFloor(editor.drawBlock.asFloor()); + } + }); + }else if(mode == 0){ //replace-only mode, doesn't affect air + editor.drawBlocks(x, y, tile -> Mathf.chance(chance) && tile.block() != Blocks.air); + }else{ + editor.drawBlocks(x, y, tile -> Mathf.chance(chance)); + } } }; - boolean edit, draggable; + /** All the internal alternate placement modes of this tool. */ + public final String[] altModes; + /** The current alternate placement mode. -1 is the standard mode, no changes.*/ + public int mode = -1; + /** Whether this tool causes canvas changes when touched.*/ + public boolean edit; + /** Whether this tool should be dragged across the canvas when the mouse moves.*/ + public boolean draggable; - public static boolean isPaint(){ - return Core.input.keyDown(KeyCode.CONTROL_LEFT); + EditorTool(){ + this(new String[]{}); } - public static boolean isAlt(){ - return Core.input.keyDown(KeyCode.TAB); + EditorTool(String... altModes){ + this.altModes = altModes; } - public static boolean isAlt2(){ - return Core.input.keyDown(KeyCode.GRAVE); - } + public void touched(MapEditor editor, int x, int y){} - public void touched(MapEditor editor, int x, int y){ - - } + public void touchedLine(MapEditor editor, int x1, int y1, int x2, int y2){} } diff --git a/core/src/io/anuke/mindustry/editor/MapEditor.java b/core/src/io/anuke/mindustry/editor/MapEditor.java index 13824d0d8a..466f513318 100644 --- a/core/src/io/anuke/mindustry/editor/MapEditor.java +++ b/core/src/io/anuke/mindustry/editor/MapEditor.java @@ -2,6 +2,8 @@ package io.anuke.mindustry.editor; import io.anuke.arc.collection.StringMap; import io.anuke.arc.files.FileHandle; +import io.anuke.arc.function.Consumer; +import io.anuke.arc.function.Predicate; import io.anuke.arc.graphics.Pixmap; import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Structs; @@ -13,7 +15,6 @@ import io.anuke.mindustry.io.MapIO; import io.anuke.mindustry.maps.Map; import io.anuke.mindustry.world.*; import io.anuke.mindustry.world.blocks.BlockPart; -import io.anuke.mindustry.world.blocks.Floor; import static io.anuke.mindustry.Vars.world; @@ -132,18 +133,19 @@ public class MapEditor{ return world.height(); } - public void draw(int x, int y, boolean paint){ - draw(x, y, paint, drawBlock); + public void drawBlocksReplace(int x, int y){ + drawBlocks(x, y, tile -> tile.block() != Blocks.air || drawBlock.isFloor()); } - public void draw(int x, int y, boolean paint, Block drawBlock){ - draw(x, y, paint, drawBlock, 1.0); + public void drawBlocks(int x, int y){ + drawBlocks(x, y, false, tile -> true); } - public void draw(int x, int y, boolean paint, Block drawBlock, double chance){ - boolean isfloor = drawBlock instanceof Floor && drawBlock != Blocks.air; - Tile[][] tiles = world.getTiles(); + public void drawBlocks(int x, int y, Predicate tester){ + drawBlocks(x, y, false, tester); + } + public void drawBlocks(int x, int y, boolean square, Predicate tester){ if(drawBlock.isMultiblock()){ 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); @@ -157,7 +159,7 @@ public class MapEditor{ int worldy = dy + offsety + y; if(Structs.inBounds(worldx, worldy, width(), height())){ - Tile tile = tiles[worldx][worldy]; + Tile tile = tile(worldx, worldy); Block block = tile.block(); @@ -171,36 +173,66 @@ public class MapEditor{ } } - world.setBlock(tiles[x][y], drawBlock, drawTeam); + world.setBlock(tile(x, y), drawBlock, 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 >= width() || wy >= height() || (paint && !isfloor && tiles[wx][wy].block() == Blocks.air)){ - continue; - } + boolean isFloor = drawBlock.isFloor() && drawBlock != Blocks.air; - Tile tile = tiles[wx][wy]; + Consumer drawer = tile -> { + if(!tester.test(tile)) return; - if(!isfloor && (tile.isLinked() || tile.block().isMultiblock())){ - world.removeBlock(tile.link()); - } + //remove linked tiles blocking the way + if(!isFloor && (tile.isLinked() || tile.block().isMultiblock())){ + world.removeBlock(tile.link()); + } - if(isfloor){ - tile.setFloor((Floor)drawBlock); - }else{ - tile.setBlock(drawBlock); - if(drawBlock.synthetic()){ - tile.setTeam(drawTeam); - } - if(drawBlock.rotate){ - tile.rotation((byte)rotation); - } - } + if(isFloor){ + tile.setFloor(drawBlock.asFloor()); + }else{ + tile.setBlock(drawBlock); + if(drawBlock.synthetic()){ + tile.setTeam(drawTeam); + } + if(drawBlock.rotate){ + tile.rotation((byte)rotation); } } + }; + + if(square){ + drawSquare(x, y, drawer); + }else{ + drawCircle(x, y, drawer); + } + } + } + + public void drawCircle(int x, int y, Consumer drawer){ + for(int rx = -brushSize; rx <= brushSize; rx++){ + for(int ry = -brushSize; ry <= brushSize; ry++){ + if(Mathf.dst2(rx, ry) <= (brushSize - 0.5f) * (brushSize - 0.5f)){ + int wx = x + rx, wy = y + ry; + + if(wx < 0 || wy < 0 || wx >= width() || wy >= height()){ + continue; + } + + drawer.accept(tile(wx, wy)); + } + } + } + } + + public void drawSquare(int x, int y, Consumer drawer){ + for(int rx = -brushSize; rx <= brushSize; rx++){ + for(int ry = -brushSize; ry <= brushSize; ry++){ + int wx = x + rx, wy = y + ry; + + if(wx < 0 || wy < 0 || wx >= width() || wy >= height()){ + continue; + } + + drawer.accept(tile(wx, wy)); } } } diff --git a/core/src/io/anuke/mindustry/editor/MapEditorDialog.java b/core/src/io/anuke/mindustry/editor/MapEditorDialog.java index df834fb7f7..934a2a5abd 100644 --- a/core/src/io/anuke/mindustry/editor/MapEditorDialog.java +++ b/core/src/io/anuke/mindustry/editor/MapEditorDialog.java @@ -12,23 +12,28 @@ import io.anuke.arc.input.KeyCode; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Vector2; import io.anuke.arc.scene.actions.Actions; +import io.anuke.arc.scene.event.Touchable; import io.anuke.arc.scene.style.TextureRegionDrawable; import io.anuke.arc.scene.ui.*; +import io.anuke.arc.scene.ui.TextButton.TextButtonStyle; import io.anuke.arc.scene.ui.layout.Table; import io.anuke.arc.scene.ui.layout.Unit; import io.anuke.arc.util.*; import io.anuke.mindustry.Vars; +import io.anuke.mindustry.content.*; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.core.Platform; import io.anuke.mindustry.game.*; -import io.anuke.mindustry.io.*; +import io.anuke.mindustry.graphics.Pal; +import io.anuke.mindustry.io.JsonIO; +import io.anuke.mindustry.io.MapIO; import io.anuke.mindustry.maps.Map; import io.anuke.mindustry.ui.dialogs.FileChooser; 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.OverlayFloor; +import io.anuke.mindustry.world.blocks.*; import io.anuke.mindustry.world.blocks.storage.CoreBlock; import static io.anuke.mindustry.Vars.*; @@ -56,12 +61,12 @@ public class MapEditorDialog extends Dialog implements Disposable{ editor = new MapEditor(); view = new MapView(editor); infoDialog = new MapInfoDialog(editor); - generateDialog = new MapGenerateDialog(editor); + generateDialog = new MapGenerateDialog(editor, true); menu = new FloatingDialog("$menu"); menu.addCloseButton(); - float isize = 16 * 2f; + float isize = iconsize; float swidth = 180f; menu.cont.table(t -> { @@ -77,7 +82,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ t.row(); t.addImageTextButton("$editor.generate", "icon-editor", isize, () -> { - generateDialog.show(); + generateDialog.show(generateDialog::applyToEditor); menu.hide(); }); @@ -259,6 +264,8 @@ public class MapEditorDialog extends Dialog implements Disposable{ private void save(){ String name = editor.getTags().get("name", "").trim(); editor.getTags().put("rules", JsonIO.write(state.rules)); + editor.getTags().remove("width"); + editor.getTags().remove("height"); player.dead = true; if(name.isEmpty()){ @@ -267,7 +274,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ }else{ Map map = world.maps.all().find(m -> m.name().equals(name)); if(map != null && !map.custom){ - ui.showError("$editor.save.overwrite"); + handleSaveBuiltin(map); }else{ world.maps.saveMap(editor.getTags()); ui.showInfoFade("$editor.saved"); @@ -278,6 +285,11 @@ public class MapEditorDialog extends Dialog implements Disposable{ saved = true; } + /** Called when a built-in map save is attempted.*/ + protected void handleSaveBuiltin(Map map){ + ui.showError("$editor.save.overwrite"); + } + /** * Argument format: * 0) button name @@ -305,7 +317,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ }).left().margin(0).get(); button.clearChildren(); - button.addImage(iconname).size(16 * 3).padLeft(10); + button.addImage(iconname).size(iconsize).padLeft(10); button.table(t -> { t.add(name).growX().wrap(); t.row(); @@ -323,7 +335,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ @Override public Dialog show(){ - return super.show(Core.scene, Actions.sequence(Actions.alpha(0f), Actions.scaleTo(1f, 1f), Actions.fadeIn(0.3f))); + return super.show(Core.scene, Actions.sequence()); } @Override @@ -360,7 +372,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ float amount = 10f, baseSize = 60f; float size = mobile ? (int)(Math.min(Core.graphics.getHeight(), Core.graphics.getWidth()) / amount / Unit.dp.scl(1f)) : - Math.min(Core.graphics.getDisplayMode().height / amount, baseSize); + Math.min(Core.graphics.getHeight() / amount, baseSize); clearChildren(); table(cont -> { @@ -372,31 +384,97 @@ public class MapEditorDialog extends Dialog implements Disposable{ Table tools = new Table().top(); ButtonGroup group = new ButtonGroup<>(); + Table[] lastTable = {null}; Consumer addTool = tool -> { - ImageButton button = new ImageButton("icon-" + tool.name(), "clear-toggle"); - button.clicked(() -> view.setTool(tool)); - button.resizeImage(16 * 2f); + + ImageButton button = new ImageButton("icon-" + tool.name() + "-small", "clear-toggle"); + button.clicked(() -> { + view.setTool(tool); + if(lastTable[0] != null){ + lastTable[0].remove(); + } + }); + button.resizeImage(iconsizesmall); button.update(() -> button.setChecked(view.getTool() == tool)); group.add(button); - if(tool == EditorTool.pencil) - button.setChecked(true); - tools.add(button); + if(tool.altModes.length > 0){ + button.clicked(l -> { + if(!mobile){ + //desktop: rightclick + l.setButton(KeyCode.MOUSE_RIGHT); + } + }, e -> { + //need to double tap + if(mobile && e.getTapCount() < 2){ + return; + } + + if(lastTable[0] != null){ + lastTable[0].remove(); + } + + Table table = new Table("dialogDim"); + table.defaults().size(300f, 70f); + + for(int i = 0; i < tool.altModes.length; i++){ + int mode = i; + String name = tool.altModes[i]; + + table.addButton(b -> { + b.left(); + b.marginLeft(6); + b.setStyle(Core.scene.skin.get("clear-toggle", TextButtonStyle.class)); + b.add(Core.bundle.get("toolmode." + name)).left(); + b.row(); + b.add(Core.bundle.get("toolmode." + name + ".description")).color(Color.LIGHT_GRAY).left(); + }, () -> { + tool.mode = (tool.mode == mode ? -1 : mode); + table.remove(); + }).update(b -> b.setChecked(tool.mode == mode)); + table.row(); + } + + table.update(() -> { + Vector2 v = button.localToStageCoordinates(Tmp.v1.setZero()); + table.setPosition(v.x, v.y, Align.topLeft); + if(!isShown()){ + table.remove(); + lastTable[0] = null; + } + }); + + table.pack(); + table.act(Core.graphics.getDeltaTime()); + + addChild(table); + lastTable[0] = table; + }); + } + + + Label mode = new Label(""); + mode.setColor(Pal.remove); + mode.update(() -> mode.setText(tool.mode == -1 ? "" : "M" + (tool.mode + 1) + " ")); + mode.setAlignment(Align.bottomRight, Align.bottomRight); + mode.touchable(Touchable.disabled); + + tools.stack(button, mode); }; tools.defaults().size(size, size); - tools.addImageButton("icon-menu-large", "clear", 16 * 2f, menu::show); + tools.addImageButton("icon-menu-large-small", "clear", iconsizesmall, menu::show); - ImageButton grid = tools.addImageButton("icon-grid", "clear-toggle", 16 * 2f, () -> view.setGrid(!view.isGrid())).get(); + ImageButton grid = tools.addImageButton("icon-grid-small", "clear-toggle", iconsizesmall, () -> view.setGrid(!view.isGrid())).get(); addTool.accept(EditorTool.zoom); tools.row(); - ImageButton undo = tools.addImageButton("icon-undo", "clear", 16 * 2f, editor::undo).get(); - ImageButton redo = tools.addImageButton("icon-redo", "clear", 16 * 2f, editor::redo).get(); + ImageButton undo = tools.addImageButton("icon-undo-small", "clear", iconsizesmall, editor::undo).get(); + ImageButton redo = tools.addImageButton("icon-redo-small", "clear", iconsizesmall, editor::redo).get(); addTool.accept(EditorTool.pick); @@ -418,7 +496,7 @@ 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.rotation = (editor.rotation + 1) % 4).get(); + ImageButton rotate = tools.addImageButton("icon-arrow-16-small", "clear", iconsizesmall, () -> editor.rotation = (editor.rotation + 1) % 4).get(); rotate.getImage().update(() -> { rotate.getImage().setRotation(editor.rotation * 90); rotate.getImage().setOrigin(Align.center); @@ -436,7 +514,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ int i = 0; for(Team team : Team.all){ - ImageButton button = new ImageButton("white", "clear-toggle-partial"); + ImageButton button = new ImageButton("whiteui", "clear-toggle-partial"); button.margin(4f); button.getImageCell().grow(); button.getStyle().imageUpColor = team.color; @@ -473,14 +551,26 @@ public class MapEditorDialog extends Dialog implements Disposable{ } private void doInput(){ - //tool select - for(int i = 0; i < EditorTool.values().length; i++){ - if(Core.input.keyTap(KeyCode.valueOf("NUM_" + (i + 1)))){ - view.setTool(EditorTool.values()[i]); - break; + + if(Core.input.ctrl()){ + //alt mode select + //TODO these keycode are unusable, tweak later + for(int i = 0; i < view.getTool().altModes.length + 1; i++){ + if(Core.input.keyTap(KeyCode.valueOf("NUM_" + (i + 1)))){ + view.getTool().mode = i - 1; + } + } + }else{ + //tool select + for(int i = 0; i < EditorTool.values().length; i++){ + if(Core.input.keyTap(KeyCode.valueOf("NUM_" + (i + 1)))){ + view.setTool(EditorTool.values()[i]); + break; + } } } + if(Core.input.keyTap(KeyCode.ESCAPE)){ if(!menu.isShown()){ menu.show(); @@ -501,6 +591,28 @@ public class MapEditorDialog extends Dialog implements Disposable{ editor.undo(); } + //more undocumented features, fantastic + if(Core.input.keyTap(KeyCode.T)){ + + //clears all 'decoration' from the map + for(int x = 0; x < editor.width(); x++){ + for(int y = 0; y < editor.height(); y++){ + Tile tile = editor.tile(x, y); + if(tile.block().breakable && tile.block() instanceof Rock){ + tile.setBlock(Blocks.air); + editor.renderer().updatePoint(x, y); + } + + if(tile.overlay() != Blocks.air && tile.overlay() != Blocks.spawn){ + tile.setOverlay(Blocks.air); + editor.renderer().updatePoint(x, y); + } + } + } + + editor.flushOp(); + } + if(Core.input.keyTap(KeyCode.Y)){ editor.redo(); } @@ -549,7 +661,7 @@ public class MapEditorDialog extends Dialog implements Disposable{ if(!Core.atlas.isFound(region)) continue; - ImageButton button = new ImageButton("white", "clear-toggle"); + ImageButton button = new ImageButton("whiteui", "clear-toggle"); button.getStyle().imageUp = new TextureRegionDrawable(region); button.clicked(() -> editor.drawBlock = block); button.resizeImage(8 * 4f); diff --git a/core/src/io/anuke/mindustry/editor/MapGenerateDialog.java b/core/src/io/anuke/mindustry/editor/MapGenerateDialog.java index 4a26bff475..545cc4004e 100644 --- a/core/src/io/anuke/mindustry/editor/MapGenerateDialog.java +++ b/core/src/io/anuke/mindustry/editor/MapGenerateDialog.java @@ -1,34 +1,38 @@ 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.Image; -import io.anuke.arc.scene.ui.layout.Stack; -import io.anuke.arc.scene.ui.layout.Table; -import io.anuke.arc.util.Scaling; -import io.anuke.arc.util.async.AsyncExecutor; -import io.anuke.arc.util.async.AsyncResult; -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 io.anuke.arc.*; +import io.anuke.arc.collection.*; +import io.anuke.arc.function.*; +import io.anuke.arc.graphics.*; +import io.anuke.arc.graphics.Pixmap.*; +import io.anuke.arc.math.*; +import io.anuke.arc.math.geom.*; +import io.anuke.arc.scene.ui.*; +import io.anuke.arc.scene.ui.layout.*; +import io.anuke.arc.util.*; +import io.anuke.arc.util.async.*; +import io.anuke.mindustry.content.*; +import io.anuke.mindustry.game.*; +import io.anuke.mindustry.graphics.*; +import io.anuke.mindustry.io.*; +import io.anuke.mindustry.maps.filters.*; +import io.anuke.mindustry.maps.filters.GenerateFilter.*; +import io.anuke.mindustry.ui.*; +import io.anuke.mindustry.ui.dialogs.*; +import io.anuke.mindustry.world.*; +import io.anuke.mindustry.world.blocks.*; import static io.anuke.mindustry.Vars.*; @SuppressWarnings("unchecked") public class MapGenerateDialog extends FloatingDialog{ - private final Supplier[] filterTypes = new Supplier[]{NoiseFilter::new, ScatterFilter::new, TerrainFilter::new, DistortFilter::new, RiverNoiseFilter::new, OreFilter::new, MedianFilter::new}; + private final Supplier[] filterTypes = new Supplier[]{ + NoiseFilter::new, ScatterFilter::new, TerrainFilter::new, DistortFilter::new, + RiverNoiseFilter::new, OreFilter::new, MedianFilter::new, BlendFilter::new, + MirrorFilter::new, ClearFilter::new + }; private final MapEditor editor; + private final boolean applied; private Pixmap pixmap; private Texture texture; @@ -43,19 +47,37 @@ public class MapGenerateDialog extends FloatingDialog{ private GenTile returnTile = new GenTile(); private GenTile[][] buffer1, buffer2; + private Consumer> applier; + private CachedTile ctile = new CachedTile(){ + //nothing. + @Override + protected void changed(){ - public MapGenerateDialog(MapEditor editor){ + } + }; + + /** @param applied whether or not to use the applied in-game mode. */ + public MapGenerateDialog(MapEditor editor, boolean applied){ super("$editor.generate"); this.editor = editor; + this.applied = applied; shown(this::setup); addCloseButton(); - buttons.addButton("$editor.apply", () -> { - ui.loadAnd(() -> { - apply(); - hide(); - }); - }).size(160f, 64f); + if(applied){ + buttons.addButton("$editor.apply", () -> { + ui.loadAnd(() -> { + apply(); + hide(); + }); + }).size(160f, 64f); + }else{ + buttons.addButton("$settings.reset", () -> { + filters.set(world.maps.readFilters("")); + rebuildFilters(); + update(); + }).size(160f, 64f); + } buttons.addButton("$editor.randomize", () -> { for(GenerateFilter filter : filters){ filter.randomize(); @@ -63,151 +85,27 @@ public class MapGenerateDialog extends FloatingDialog{ update(); }).size(160f, 64f); - buttons.addImageTextButton("$add", "icon-add", 14 * 2, this::showAdd).height(64f).width(140f); + buttons.addImageTextButton("$add", "icon-add", iconsize, this::showAdd).height(64f).width(140f); + + if(!applied){ + hidden(this::apply); + } + + onResize(this::rebuildFilters); } - 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.stack(new BorderImage(texture){{ - setScaling(Scaling.fit); - }}, new Stack(){{ - add(new Image("loadDim")); - add(new Image("icon-refresh"){{ - setScaling(Scaling.none); - }}); - visible(() -> generating && !updateEditorOnChange); - }}).size(mobile ? 300f : 400f).padRight(6); - t.pane(p -> filterTable = p).width(300f).get().setScrollingDisabled(true, false); - }).grow(); - - buffer1 = create(); - buffer2 = create(); - - update(); - rebuildFilters(); + public void show(Array filters, Consumer> applier){ + this.filters = filters; + this.applier = applier; + show(); } - GenTile[][] create(){ - GenTile[][] out = new GenTile[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 GenTile(); - } - } - return out; + public void show(Consumer> applier){ + show(this.filters, applier); } - 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(); - } - - GenTile dset(Tile tile){ - returnTile.set(tile); - return returnTile; - } - - void apply(){ - if(result != null){ - result.get(); - } - - buffer1 = null; - buffer2 = null; - generating = false; - if(pixmap != null){ - pixmap.dispose(); - texture.dispose(); - pixmap = null; - texture = null; - } - + /** Applies the specified filters to the editor. */ + public void applyToEditor(Array filters){ //writeback buffer GenTile[][] writeTiles = new GenTile[editor.width()][editor.height()]; @@ -218,12 +116,12 @@ public class MapGenerateDialog extends FloatingDialog{ } for(GenerateFilter filter : filters){ - input.setFilter(filter, editor.width(), editor.height(), 1, (x, y) -> dset(editor.tile(x, y))); + input.begin(filter, editor.width(), editor.height(), editor::tile); //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.overlay()); + input.apply(x, y, tile.floor(), tile.block(), tile.overlay()); filter.apply(input); writeTiles[x][y].set(input.floor, input.block, input.ore, tile.getTeam(), tile.rotation()); } @@ -252,6 +150,204 @@ public class MapGenerateDialog extends FloatingDialog{ editor.clearOp(); } + public void addDefaultOres(Array filters){ + int index = 0; + for(Block block : new Block[]{Blocks.oreCopper, Blocks.oreLead, Blocks.oreCoal, Blocks.oreTitanium, Blocks.oreThorium}){ + OreFilter filter = new OreFilter(); + filter.threshold += index ++ * 0.019f; + filter.ore = block; + filters.add(filter); + } + } + + 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(t -> { + t.margin(8f); + t.stack(new BorderImage(texture){ + { + setScaling(Scaling.fit); + } + + @Override + public void draw(){ + super.draw(); + for(GenerateFilter filter : filters){ + filter.draw(this); + } + } + }, new Stack(){{ + add(new Image("loadDim")); + add(new Image("icon-refresh"){{ + setScaling(Scaling.none); + }}); + visible(() -> generating && !updateEditorOnChange); + }}).grow().padRight(10); + t.pane(p -> filterTable = p.marginRight(6)).update(pane -> { + if(Core.scene.getKeyboardFocus() instanceof Dialog && Core.scene.getKeyboardFocus() != this){ + return; + } + + Vector2 v = pane.stageToLocalCoordinates(Core.input.mouse()); + + if(v.x >= 0 && v.y >= 0 && v.x <= pane.getWidth() && v.y <= pane.getHeight()){ + Core.scene.setScrollFocus(pane); + }else{ + Core.scene.setScrollFocus(null); + } + }).grow().get().setScrollingDisabled(true, false); + }).grow(); + + buffer1 = create(); + buffer2 = create(); + + update(); + rebuildFilters(); + } + + GenTile[][] create(){ + GenTile[][] out = new GenTile[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 GenTile(); + } + } + return out; + } + + void rebuildFilters(){ + int cols = Math.max((int)(Math.max(filterTable.getParent().getWidth(), Core.graphics.getWidth()/2f * 0.9f) / Unit.dp.scl(290f)), 1); + filterTable.clearChildren(); + filterTable.top().left(); + int i = 0; + + for(GenerateFilter filter : filters){ + + //main container + filterTable.table("button", c -> { + //icons to perform actions + c.table(t -> { + t.top(); + t.add(filter.name()).padTop(5).color(Pal.accent).growX().left(); + + t.row(); + + t.table(b -> { + String style = "clear"; + b.defaults().size(50f); + b.addImageButton("icon-refresh-small", style, iconsizesmall, () -> { + filter.randomize(); + update(); + }); + + b.addImageButton("icon-arrow-up-small", style, iconsizesmall, () -> { + int idx = filters.indexOf(filter); + filters.swap(idx, Math.max(0, idx - 1)); + rebuildFilters(); + update(); + }); + b.addImageButton("icon-arrow-down-small",style, iconsizesmall, () -> { + int idx = filters.indexOf(filter); + filters.swap(idx, Math.min(filters.size - 1, idx + 1)); + rebuildFilters(); + update(); + }); + b.addImageButton("icon-trash-small", style, iconsizesmall, () -> { + filters.remove(filter); + rebuildFilters(); + update(); + }); + }); + }).fillX(); + c.row(); + //all the options + c.table(f -> { + f.left().top(); + for(FilterOption option : filter.options){ + option.changed = this::update; + + f.table(t -> { + t.left(); + option.build(t); + }).growX().left(); + f.row(); + } + }).grow().left().pad(2).top(); + }).width(280f).pad(3).top().left().fillY(); + if(++i % cols == 0){ + 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(); + + if(!applied && filter.buffered) continue; + + selection.cont.addButton(filter.name(), () -> { + filters.add(filter); + rebuildFilters(); + update(); + selection.hide(); + }); + if(++i % 2 == 0) selection.cont.row(); + } + + selection.cont.addButton("$filter.defaultores", () -> { + addDefaultOres(filters); + rebuildFilters(); + update(); + selection.hide(); + }); + + selection.addCloseButton(); + selection.show(); + } + + GenTile dset(Tile tile){ + returnTile.set(tile); + return returnTile; + } + + void apply(){ + if(result != null){ + result.get(); + } + + buffer1 = null; + buffer2 = null; + generating = false; + if(pixmap != null){ + pixmap.dispose(); + texture.dispose(); + pixmap = null; + texture = null; + } + + applier.accept(filters); + } + void update(){ if(generating){ @@ -274,13 +370,13 @@ public class MapGenerateDialog extends FloatingDialog{ } for(GenerateFilter filter : copy){ - input.setFilter(filter, pixmap.getWidth(), pixmap.getHeight(), scaling, (x, y) -> buffer1[x][y]); + input.begin(filter, editor.width(), editor.height(), (x, y) -> buffer1[Mathf.clamp(x / scaling, 0, pixmap.getWidth()-1)][Mathf.clamp(y / scaling, 0, pixmap.getHeight()-1)].tile()); //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; GenTile tile = buffer1[px][py]; - input.begin(editor, x, y, content.block(tile.floor), content.block(tile.block), content.block(tile.ore)); + input.apply(x, y, content.block(tile.floor), content.block(tile.block), content.block(tile.ore)); filter.apply(input); buffer2[px][py].set(input.floor, input.block, input.ore, Team.all[tile.team], tile.rotation); } @@ -322,11 +418,11 @@ public class MapGenerateDialog extends FloatingDialog{ }); } - public static class GenTile{ + private class GenTile{ public byte team, rotation; public short block, floor, ore; - void set(Block floor, Block wall, Block ore, Team team, int rotation){ + public void set(Block floor, Block wall, Block ore, Team team, int rotation){ this.floor = floor.id; this.block = wall.id; this.ore = ore.id; @@ -334,7 +430,7 @@ public class MapGenerateDialog extends FloatingDialog{ this.rotation = (byte)rotation; } - void set(GenTile other){ + public void set(GenTile other){ this.floor = other.floor; this.block = other.block; this.ore = other.ore; @@ -342,9 +438,18 @@ public class MapGenerateDialog extends FloatingDialog{ this.rotation = other.rotation; } - void set(Tile other){ + public GenTile set(Tile other){ set(other.floor(), other.block(), other.overlay(), other.getTeam(), other.rotation()); + return this; } + Tile tile(){ + ctile.setFloor((Floor)content.block(floor)); + ctile.setBlock(content.block(block)); + ctile.setOverlay(content.block(ore)); + ctile.rotation(rotation); + ctile.setTeam(Team.all[team]); + return ctile; + } } } diff --git a/core/src/io/anuke/mindustry/editor/MapInfoDialog.java b/core/src/io/anuke/mindustry/editor/MapInfoDialog.java index 7f9fca20e6..82ee7bcd6d 100644 --- a/core/src/io/anuke/mindustry/editor/MapInfoDialog.java +++ b/core/src/io/anuke/mindustry/editor/MapInfoDialog.java @@ -1,24 +1,27 @@ package io.anuke.mindustry.editor; -import io.anuke.arc.Core; -import io.anuke.arc.collection.ObjectMap; -import io.anuke.arc.scene.ui.TextArea; -import io.anuke.arc.scene.ui.TextField; -import io.anuke.mindustry.Vars; -import io.anuke.mindustry.core.Platform; -import io.anuke.mindustry.game.Rules; -import io.anuke.mindustry.ui.dialogs.CustomRulesDialog; -import io.anuke.mindustry.ui.dialogs.FloatingDialog; +import io.anuke.arc.*; +import io.anuke.arc.collection.*; +import io.anuke.arc.scene.ui.*; +import io.anuke.mindustry.*; +import io.anuke.mindustry.core.*; +import io.anuke.mindustry.game.*; +import io.anuke.mindustry.io.*; +import io.anuke.mindustry.ui.dialogs.*; + +import static io.anuke.mindustry.Vars.world; public class MapInfoDialog extends FloatingDialog{ private final MapEditor editor; private final WaveInfoDialog waveInfo; + private final MapGenerateDialog generate; private final CustomRulesDialog ruleInfo = new CustomRulesDialog(); public MapInfoDialog(MapEditor editor){ super("$editor.mapinfo"); this.editor = editor; this.waveInfo = new WaveInfoDialog(editor); + this.generate = new MapGenerateDialog(editor, false); addCloseButton(); @@ -29,47 +32,56 @@ public class MapInfoDialog extends FloatingDialog{ cont.clear(); ObjectMap tags = editor.getTags(); + + cont.pane(t -> { + t.add("$editor.name").padRight(8).left(); + t.defaults().padTop(15); - cont.add("$editor.name").padRight(8).left(); + TextField name = t.addField(tags.get("name", ""), text -> { + tags.put("name", text); + }).size(400, 55f).get(); + name.setMessageText("$unknown"); - cont.defaults().padTop(15); + t.row(); + t.add("$editor.description").padRight(8).left(); - TextField name = cont.addField(tags.get("name", ""), text -> { - tags.put("name", text); - }).size(400, 55f).get(); - name.setMessageText("$unknown"); + TextArea description = t.addArea(tags.get("description", ""), "textarea", text -> { + tags.put("description", text); + }).size(400f, 140f).get(); - cont.row(); - cont.add("$editor.description").padRight(8).left(); + t.row(); + t.add("$editor.author").padRight(8).left(); - TextArea description = cont.addArea(tags.get("description", ""), "textarea", text -> { - tags.put("description", text); - }).size(400f, 140f).get(); + TextField author = t.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.author").padRight(8).left(); + t.row(); + t.add("$editor.rules").padRight(8).left(); + t.addButton("$edit", () -> ruleInfo.show(Vars.state.rules, () -> Vars.state.rules = new Rules())).left().width(200f); - 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"); + t.row(); + t.add("$editor.waves").padRight(8).left(); + t.addButton("$edit", waveInfo::show).left().width(200f); - cont.row(); - cont.add("$editor.rules").padRight(8).left(); - cont.addButton("$edit", () -> ruleInfo.show(Vars.state.rules, () -> Vars.state.rules = new Rules())).left().width(200f);; + t.row(); + t.add("$editor.generation").padRight(8).left(); + t.addButton("$edit", + () -> generate.show(world.maps.readFilters(editor.getTags().get("genfilters", "")), + filters -> editor.getTags().put("genfilters", JsonIO.write(filters))) + ).left().width(200f); - cont.row(); - cont.add("$editor.waves").padRight(8).left(); - cont.addButton("$edit", waveInfo::show).left().width(200f); + name.change(); + description.change(); + author.change(); - name.change(); - description.change(); - author.change(); - - Platform.instance.addDialog(name, 50); - Platform.instance.addDialog(author, 50); - Platform.instance.addDialog(description, 1000); + Platform.instance.addDialog(name, 50); + Platform.instance.addDialog(author, 50); + Platform.instance.addDialog(description, 1000); + t.margin(16f); + }); } } diff --git a/core/src/io/anuke/mindustry/editor/MapRenderer.java b/core/src/io/anuke/mindustry/editor/MapRenderer.java index 3bca816d61..0be885abab 100644 --- a/core/src/io/anuke/mindustry/editor/MapRenderer.java +++ b/core/src/io/anuke/mindustry/editor/MapRenderer.java @@ -118,10 +118,12 @@ public class MapRenderer implements Disposable{ wx * tilesize + wall.offset(), wy * tilesize + wall.offset(), region.getWidth() * Draw.scl, region.getHeight() * Draw.scl, tile.rotation() * 90 - 90); }else{ + float width = region.getWidth() * Draw.scl, height = region.getHeight() * Draw.scl; + mesh.draw(idxWall, region, - wx * tilesize + wall.offset() + (tilesize - region.getWidth() * Draw.scl) / 2f, - wy * tilesize + wall.offset() + (tilesize - region.getHeight() * Draw.scl) / 2f, - region.getWidth() * Draw.scl, region.getHeight() * Draw.scl); + wx * tilesize + wall.offset() + (tilesize - width) / 2f, + wy * tilesize + wall.offset() + (tilesize - height) / 2f, + width, height); } }else{ region = floor.editorVariantRegions()[Mathf.randomSeed(idxWall, 0, floor.editorVariantRegions().length - 1)]; @@ -144,9 +146,15 @@ public class MapRenderer implements Disposable{ region = Core.atlas.find("clear-editor"); } - mesh.draw(idxDecal, region, - wx * tilesize + offsetX, wy * tilesize + offsetY, - region.getWidth() * Draw.scl, region.getHeight() * Draw.scl); + float width = region.getWidth() * Draw.scl, height = region.getHeight() * Draw.scl; + if(!wall.synthetic() && wall != Blocks.air && !wall.isMultiblock()){ + offsetX = 0; + offsetY = 0; + width = tilesize; + height = tilesize; + } + + mesh.draw(idxDecal, region, wx * tilesize + offsetX, wy * tilesize + offsetY, width, height); mesh.setColor(Color.WHITE); } diff --git a/core/src/io/anuke/mindustry/editor/MapView.java b/core/src/io/anuke/mindustry/editor/MapView.java index a332dd3adc..59958e548e 100644 --- a/core/src/io/anuke/mindustry/editor/MapView.java +++ b/core/src/io/anuke/mindustry/editor/MapView.java @@ -1,7 +1,6 @@ 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.graphics.g2d.*; import io.anuke.arc.input.GestureDetector; @@ -13,7 +12,7 @@ import io.anuke.arc.scene.Element; import io.anuke.arc.scene.event.*; import io.anuke.arc.scene.ui.TextField; import io.anuke.arc.scene.ui.layout.Unit; -import io.anuke.arc.util.Tmp; +import io.anuke.arc.util.*; import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.input.Binding; import io.anuke.mindustry.ui.GridImage; @@ -24,7 +23,6 @@ import static io.anuke.mindustry.Vars.ui; public class MapView extends Element implements GestureListener{ private MapEditor editor; private EditorTool tool = EditorTool.pencil; - private Bresenham2 br = new Bresenham2(); private float offsetx, offsety; private float zoom = 1f; private boolean grid = false; @@ -107,19 +105,8 @@ public class MapView extends Element implements GestureListener{ Point2 p = project(x, y); if(tool == EditorTool.line){ - if(Core.input.keyDown(KeyCode.TAB)){ - if(Math.abs(p.x - firstTouch.x) > Math.abs(p.y - firstTouch.y)){ - p.y = firstTouch.y; - }else{ - p.x = firstTouch.x; - } - } - ui.editor.resetSaved(); - Array points = br.line(startx, starty, p.x, p.y); - for(Point2 point : points){ - editor.draw(point.x, point.y, EditorTool.isPaint()); - } + tool.touchedLine(editor, startx, starty, p.x, p.y); } editor.flushOp(); @@ -133,7 +120,6 @@ public class MapView extends Element implements GestureListener{ @Override public void touchDragged(InputEvent event, float x, float y, int pointer){ - mousex = x; mousey = y; @@ -141,13 +127,10 @@ public class MapView extends Element implements GestureListener{ if(drawing && tool.draggable && !(p.x == lastx && p.y == lasty)){ ui.editor.resetSaved(); - Array points = br.line(lastx, lasty, p.x, p.y); - for(Point2 point : points){ - tool.touched(editor, point.x, point.y); - } + Bresenham2.line(lastx, lasty, p.x, p.y, (cx, cy) -> tool.touched(editor, cx, cy)); } - if(tool == EditorTool.line && Core.input.keyDown(KeyCode.TAB)){ + if(tool == EditorTool.line && tool.mode == 1){ if(Math.abs(p.x - firstTouch.x) > Math.abs(p.y - firstTouch.y)){ lastx = p.x; lasty = firstTouch.y; @@ -254,9 +237,7 @@ public class MapView extends Element implements GestureListener{ Draw.color(Pal.remove); Lines.stroke(2f); Lines.rect(centerx - sclwidth / 2 - 1, centery - sclheight / 2 - 1, sclwidth + 2, sclheight + 2); - if(Core.scene.getKeyboardFocus() != null && isDescendantOf(Core.scene.getKeyboardFocus())){ - editor.renderer().draw(centerx - sclwidth / 2, centery - sclheight / 2, sclwidth, sclheight); - } + editor.renderer().draw(centerx - sclwidth / 2, centery - sclheight / 2, sclwidth, sclheight); Draw.reset(); if(!ScissorStack.pushScissors(rect.set(x, y, width, height))){ @@ -296,7 +277,13 @@ public class MapView extends Element implements GestureListener{ if((tool.edit || (tool == EditorTool.line && !drawing)) && (!mobile || drawing)){ Point2 p = project(mousex, mousey); Vector2 v = unproject(p.x, p.y).add(x, y); - Lines.poly(brushPolygons[index], v.x, v.y, scaling); + + //pencil square outline + if(tool == EditorTool.pencil && tool.mode == 1){ + Lines.square(v.x + scaling/2f, v.y + scaling/2f, scaling * (editor.brushSize + 0.5f)); + }else{ + Lines.poly(brushPolygons[index], v.x, v.y, scaling); + } } }else{ if((tool.edit || tool == EditorTool.line) && (!mobile || drawing)){ diff --git a/core/src/io/anuke/mindustry/editor/WaveInfoDialog.java b/core/src/io/anuke/mindustry/editor/WaveInfoDialog.java index 4a7945af2c..12098e5884 100644 --- a/core/src/io/anuke/mindustry/editor/WaveInfoDialog.java +++ b/core/src/io/anuke/mindustry/editor/WaveInfoDialog.java @@ -5,6 +5,8 @@ import io.anuke.arc.collection.Array; import io.anuke.arc.graphics.Color; import io.anuke.arc.input.KeyCode; import io.anuke.arc.math.Mathf; +import io.anuke.arc.scene.event.Touchable; +import io.anuke.arc.scene.ui.Label; import io.anuke.arc.scene.ui.TextField.TextFieldFilter; import io.anuke.arc.scene.ui.layout.Table; import io.anuke.arc.util.*; @@ -21,7 +23,7 @@ import static io.anuke.mindustry.game.SpawnGroup.never; public class WaveInfoDialog extends FloatingDialog{ private final static int displayed = 20; - private Array groups; + private Array groups = new Array<>(); private Table table, preview; private int start = 0; @@ -50,22 +52,22 @@ public class WaveInfoDialog extends FloatingDialog{ dialog.cont.defaults().size(210f, 64f); dialog.cont.addButton("$waves.copy", () -> { ui.showInfoFade("$waves.copied"); - Core.app.getClipboard().setContents(world.maps.writeWaves(groups)); + Core.app.setClipboardText(world.maps.writeWaves(groups)); dialog.hide(); }).disabled(b -> groups == null); dialog.cont.row(); dialog.cont.addButton("$waves.load", () -> { try{ - groups = world.maps.readWaves(Core.app.getClipboard().getContents()); + groups = world.maps.readWaves(Core.app.getClipboardText()); buildGroups(); }catch(Exception e){ ui.showError("$waves.invalid"); } dialog.hide(); - }).disabled(b -> Core.app.getClipboard().getContents() == null || Core.app.getClipboard().getContents().isEmpty()); + }).disabled(b -> Core.app.getClipboardText() == null || Core.app.getClipboardText().isEmpty()); dialog.cont.row(); dialog.cont.addButton("$settings.reset", () -> ui.showConfirm("$confirm", "$settings.clear.confirm", () -> { - groups = JsonIO.copy(DefaultWaves.get()); + groups = JsonIO.copy(defaultWaves.get()); buildGroups(); dialog.hide(); })); @@ -74,18 +76,24 @@ public class WaveInfoDialog extends FloatingDialog{ } void setup(){ - groups = JsonIO.copy(state.rules.spawns); + groups = JsonIO.copy(state.rules.spawns.isEmpty() ? defaultWaves.get() : state.rules.spawns); cont.clear(); - cont.table("clear", main -> { - main.pane(t -> table = t).growX().growY().get().setScrollingDisabled(true, false); + cont.stack(new Table("clear", main -> { + main.pane(t -> table = t).growX().growY().padRight(8f).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(); + }), new Label("$waves.none"){{ + visible(groups::isEmpty); + touchable(Touchable.disabled); + setWrap(true); + setAlignment(Align.center, Align.center); + }}).width(390f).growY(); + cont.table("clear", m -> { m.add("$waves.preview").color(Color.LIGHT_GRAY).growX().center().get().setAlignment(Align.center, Align.center); m.row(); @@ -101,7 +109,7 @@ public class WaveInfoDialog extends FloatingDialog{ } }).growX().height(70f); m.row(); - m.pane(t -> preview = t).grow().get().setScrollingDisabled(true, false); + m.pane(t -> preview = t).grow().get().setScrollingDisabled(true, true); m.row(); m.addButton("+", () -> { }).update(t -> { @@ -126,8 +134,8 @@ public class WaveInfoDialog extends FloatingDialog{ if(groups != null){ for(SpawnGroup group : groups){ - table.table("clear", t -> { - t.margin(6f).defaults().pad(2).padLeft(5f).growX().left(); + table.table("button", t -> { + t.margin(0).defaults().pad(3).padLeft(5f).growX().left(); t.addButton(b -> { b.left(); b.addImage(group.type.iconRegion).size(30f).padRight(3); @@ -194,7 +202,7 @@ public class WaveInfoDialog extends FloatingDialog{ t.remove(); updateWaves(); }).growX().pad(-6f).padTop(5); - }).width(340f).pad(5); + }).width(340f).pad(16); table.row(); } }else{ diff --git a/core/src/io/anuke/mindustry/editor/generation/DistortFilter.java b/core/src/io/anuke/mindustry/editor/generation/DistortFilter.java deleted file mode 100644 index 3fab21d3a5..0000000000 --- a/core/src/io/anuke/mindustry/editor/generation/DistortFilter.java +++ /dev/null @@ -1,27 +0,0 @@ -package io.anuke.mindustry.editor.generation; - -import io.anuke.mindustry.editor.MapGenerateDialog.GenTile; -import io.anuke.mindustry.editor.generation.FilterOption.SliderOption; -import io.anuke.mindustry.world.blocks.Floor; - -import static io.anuke.mindustry.Vars.content; - -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(){ - GenTile tile = in.tile(in.x / (in.scaling) + (noise(in.x, in.y, scl, mag) - mag / 2f) / in.scaling, in.y / (in.scaling) + (noise(in.x, in.y + o, scl, mag) - mag / 2f) / in.scaling); - - in.floor = content.block(tile.floor); - if(!content.block(tile.block).synthetic() && !in.block.synthetic()) in.block = content.block(tile.block); - if(!((Floor)in.floor).isLiquid) in.ore = content.block(tile.ore); - } -} diff --git a/core/src/io/anuke/mindustry/editor/generation/ScatterFilter.java b/core/src/io/anuke/mindustry/editor/generation/ScatterFilter.java deleted file mode 100644 index 4c05603006..0000000000 --- a/core/src/io/anuke/mindustry/editor/generation/ScatterFilter.java +++ /dev/null @@ -1,30 +0,0 @@ -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/entities/Effects.java b/core/src/io/anuke/mindustry/entities/Effects.java index 4a2f964b61..625d4b69e9 100644 --- a/core/src/io/anuke/mindustry/entities/Effects.java +++ b/core/src/io/anuke/mindustry/entities/Effects.java @@ -14,7 +14,7 @@ public class Effects{ private static final EffectContainer container = new EffectContainer(); private static Array effects = new Array<>(); private static ScreenshakeProvider shakeProvider; - private static float shakeFalloff = 1000f; + private static float shakeFalloff = 10000f; private static EffectProvider provider = (effect, color, x, y, rotation, data) -> { EffectEntity entity = Pools.obtain(EffectEntity.class, EffectEntity::new); entity.effect = effect; diff --git a/core/src/io/anuke/mindustry/entities/Entities.java b/core/src/io/anuke/mindustry/entities/Entities.java index d0d5d16dea..2a6f388ff5 100755 --- a/core/src/io/anuke/mindustry/entities/Entities.java +++ b/core/src/io/anuke/mindustry/entities/Entities.java @@ -13,7 +13,6 @@ import io.anuke.mindustry.entities.traits.Entity; import static io.anuke.mindustry.Vars.collisions; public class Entities{ - public static final int maxLeafObjects = 4; private static final Array> groupArray = new Array<>(); private static final IntMap> groups = new IntMap<>(); private static final Rectangle viewport = new Rectangle(); diff --git a/core/src/io/anuke/mindustry/entities/EntityCollisions.java b/core/src/io/anuke/mindustry/entities/EntityCollisions.java index 3d98f80d35..808f8e4fc8 100644 --- a/core/src/io/anuke/mindustry/entities/EntityCollisions.java +++ b/core/src/io/anuke/mindustry/entities/EntityCollisions.java @@ -1,11 +1,14 @@ package io.anuke.mindustry.entities; import io.anuke.arc.collection.Array; -import io.anuke.arc.collection.IntSet; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.*; import io.anuke.mindustry.entities.traits.Entity; import io.anuke.mindustry.entities.traits.SolidTrait; +import io.anuke.mindustry.world.Tile; + +import static io.anuke.mindustry.Vars.tilesize; +import static io.anuke.mindustry.Vars.world; public class EntityCollisions{ //range for tile collision scanning @@ -14,29 +17,15 @@ public class EntityCollisions{ private static final float seg = 1f; //tile collisions - private float tilesize; private Rectangle tmp = new Rectangle(); - private TileCollider collider; - private TileHitboxProvider hitboxProvider; private Vector2 vector = new Vector2(); private Vector2 l1 = new Vector2(); private Rectangle r1 = new Rectangle(); private Rectangle r2 = new Rectangle(); //entity collisions - private IntSet collided = new IntSet(); private Array arrOut = new Array<>(); - public void setCollider(float tilesize, TileCollider collider, TileHitboxProvider hitbox){ - this.tilesize = tilesize; - this.collider = collider; - this.hitboxProvider = hitbox; - } - - public void setCollider(float tilesize, TileCollider collider){ - setCollider(tilesize, collider, (x, y, out) -> out.setSize(tilesize).setCenter(x * tilesize, y * tilesize)); - } - public void move(SolidTrait entity, float deltax, float deltay){ boolean movedx = false; @@ -67,8 +56,6 @@ public class EntityCollisions{ } public void moveDelta(SolidTrait entity, float deltax, float deltay, boolean x){ - if(collider == null) - throw new IllegalArgumentException("No tile collider specified! Call setCollider() first."); Rectangle rect = r1; entity.hitboxTile(rect); @@ -81,9 +68,8 @@ public class EntityCollisions{ for(int dx = -r; dx <= r; dx++){ for(int dy = -r; dy <= r; dy++){ int wx = dx + tilex, wy = dy + tiley; - if(collider.solid(wx, wy) && entity.collidesGrid(wx, wy)){ - - hitboxProvider.getHitbox(wx, wy, tmp); + if(solid(wx, wy) && entity.collidesGrid(wx, wy)){ + tmp.setSize(tilesize).setCenter(wx * tilesize, wy * tilesize); if(tmp.overlaps(rect)){ Vector2 v = Geometry.overlap(rect, tmp, x); @@ -99,9 +85,6 @@ public class EntityCollisions{ } public boolean overlapsTile(Rectangle rect){ - if(collider == null) - throw new IllegalArgumentException("No tile collider specified! Call setCollider() first."); - rect.getCenter(vector); int r = 1; @@ -112,8 +95,8 @@ public class EntityCollisions{ for(int dx = -r; dx <= r; dx++){ for(int dy = -r; dy <= r; dy++){ int wx = dx + tilex, wy = dy + tiley; - if(collider.solid(wx, wy)){ - hitboxProvider.getHitbox(wx, wy, r2); + if(solid(wx, wy)){ + r2.setSize(tilesize).setCenter(wx * tilesize, wy * tilesize); if(r2.overlaps(rect)){ return true; @@ -126,7 +109,6 @@ public class EntityCollisions{ @SuppressWarnings("unchecked") public void updatePhysics(EntityGroup group){ - collided.clear(); QuadTree tree = group.tree(); tree.clear(); @@ -140,6 +122,11 @@ public class EntityCollisions{ } } + private static boolean solid(int x, int y){ + Tile tile = world.tile(x, y); + return tile != null && tile.solid(); + } + private void checkCollide(Entity entity, Entity other){ SolidTrait a = (SolidTrait)entity; @@ -221,10 +208,9 @@ public class EntityCollisions{ @SuppressWarnings("unchecked") public void collideGroups(EntityGroup groupa, EntityGroup groupb){ - collided.clear(); for(Entity entity : groupa.all()){ - if(!(entity instanceof SolidTrait) || collided.contains(entity.getID())) + if(!(entity instanceof SolidTrait)) continue; SolidTrait solid = (SolidTrait)entity; @@ -241,20 +227,10 @@ public class EntityCollisions{ for(SolidTrait sc : arrOut){ sc.hitbox(r1); - if(r2.overlaps(r1) && !collided.contains(sc.getID())){ + if(r2.overlaps(r1)){ checkCollide(entity, sc); } } - - collided.add(entity.getID()); } } - - public interface TileCollider{ - boolean solid(int x, int y); - } - - public interface TileHitboxProvider{ - void getHitbox(int x, int y, Rectangle out); - } } diff --git a/core/src/io/anuke/mindustry/entities/EntityGroup.java b/core/src/io/anuke/mindustry/entities/EntityGroup.java index 314aa63d76..d3010c84f3 100644 --- a/core/src/io/anuke/mindustry/entities/EntityGroup.java +++ b/core/src/io/anuke/mindustry/entities/EntityGroup.java @@ -17,7 +17,7 @@ public class EntityGroup{ private final Array entitiesToRemove = new Array<>(false, 16); private final Array entitiesToAdd = new Array<>(false, 16); private IntMap map; - private QuadTree tree; + private QuadTree tree; private Consumer removeListener; private Consumer addListener; @@ -27,7 +27,7 @@ public class EntityGroup{ this.type = type; if(useTree){ - tree = new QuadTree<>(Entities.maxLeafObjects, new Rectangle(0, 0, 0, 0)); + tree = new QuadTree<>(new Rectangle(0, 0, 0, 0)); } } @@ -124,7 +124,7 @@ public class EntityGroup{ /** Resizes the internal quadtree, if it is enabled.*/ public void resize(float x, float y, float w, float h){ if(useTree){ - tree = new QuadTree<>(Entities.maxLeafObjects, new Rectangle(x, y, w, h)); + tree = new QuadTree<>(new Rectangle(x, y, w, h)); } } diff --git a/core/src/io/anuke/mindustry/entities/bullet/Bullet.java b/core/src/io/anuke/mindustry/entities/bullet/Bullet.java index 2ff39fcc6f..4060376c14 100644 --- a/core/src/io/anuke/mindustry/entities/bullet/Bullet.java +++ b/core/src/io/anuke/mindustry/entities/bullet/Bullet.java @@ -16,11 +16,10 @@ import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.world.Tile; -import java.io.*; +import static io.anuke.mindustry.Vars.bulletGroup; +import static io.anuke.mindustry.Vars.world; -import static io.anuke.mindustry.Vars.*; - -public class Bullet extends SolidEntity implements DamageTrait, ScaleTrait, Poolable, DrawTrait, VelocityTrait, TimeTrait, TeamTrait, SyncTrait, AbsorbTrait{ +public class Bullet extends SolidEntity implements DamageTrait, ScaleTrait, Poolable, DrawTrait, VelocityTrait, TimeTrait, TeamTrait, AbsorbTrait{ public Interval timer = new Interval(3); private float lifeScl; @@ -153,31 +152,6 @@ public class Bullet extends SolidEntity implements DamageTrait, ScaleTrait, Pool return type.damage * damageMultiplier(); } - @Override - public boolean isSyncing(){ - return type.syncable; - } - - @Override - public void write(DataOutput data) throws IOException{ - data.writeFloat(x); - data.writeFloat(y); - data.writeFloat(velocity.x); - data.writeFloat(velocity.y); - data.writeByte(team.ordinal()); - data.writeByte(type.id); - } - - @Override - public void read(DataInput data) throws IOException{ - x = data.readFloat(); - y = data.readFloat(); - velocity.x = data.readFloat(); - velocity.y = data.readFloat(); - team = Team.all[data.readByte()]; - type = content.bullet(data.readByte()); - } - @Override public Team getTeam(){ return team; diff --git a/core/src/io/anuke/mindustry/entities/bullet/BulletType.java b/core/src/io/anuke/mindustry/entities/bullet/BulletType.java index 3bda06008a..b554c2ac68 100644 --- a/core/src/io/anuke/mindustry/entities/bullet/BulletType.java +++ b/core/src/io/anuke/mindustry/entities/bullet/BulletType.java @@ -46,8 +46,6 @@ public abstract class BulletType extends Content{ public StatusEffect status = StatusEffects.none; /** Intensity of applied status effect in terms of duration. */ public float statusDuration = 60 * 1f; - /** Whether to sync this bullet to clients. */ - public boolean syncable; /** Whether this bullet type collides with tiles. */ public boolean collidesTiles = true; /** Whether this bullet type collides with tiles that are of the same team. */ diff --git a/core/src/io/anuke/mindustry/entities/effect/Fire.java b/core/src/io/anuke/mindustry/entities/effect/Fire.java index a7eb817a15..19ceadf09c 100644 --- a/core/src/io/anuke/mindustry/entities/effect/Fire.java +++ b/core/src/io/anuke/mindustry/entities/effect/Fire.java @@ -5,13 +5,15 @@ import io.anuke.arc.collection.IntMap; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Geometry; import io.anuke.arc.math.geom.Point2; -import io.anuke.arc.util.*; +import io.anuke.arc.util.Structs; +import io.anuke.arc.util.Time; import io.anuke.mindustry.content.*; import io.anuke.mindustry.entities.*; import io.anuke.mindustry.entities.impl.TimedEntity; import io.anuke.mindustry.entities.traits.SaveTrait; import io.anuke.mindustry.entities.traits.SyncTrait; import io.anuke.mindustry.entities.type.TileEntity; +import io.anuke.mindustry.game.TypeID; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.world.*; @@ -75,6 +77,11 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait{ } } + @Override + public TypeID getTypeID(){ + return TypeIDs.fire; + } + @Override public byte version(){ return 0; @@ -96,6 +103,7 @@ public class Fire extends TimedEntity implements SaveTrait, SyncTrait{ } time = Mathf.clamp(time + Time.delta(), 0, lifetime()); + map.put(tile.pos(), this); if(Net.client()){ return; diff --git a/core/src/io/anuke/mindustry/entities/effect/Lightning.java b/core/src/io/anuke/mindustry/entities/effect/Lightning.java index b3e72ca915..bc842d7d95 100644 --- a/core/src/io/anuke/mindustry/entities/effect/Lightning.java +++ b/core/src/io/anuke/mindustry/entities/effect/Lightning.java @@ -14,18 +14,16 @@ import io.anuke.mindustry.entities.EntityGroup; import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.entities.bullet.Bullet; import io.anuke.mindustry.entities.impl.TimedEntity; -import io.anuke.mindustry.entities.traits.*; +import io.anuke.mindustry.entities.traits.DrawTrait; +import io.anuke.mindustry.entities.traits.TimeTrait; import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.graphics.Pal; -import java.io.DataInput; -import java.io.DataOutput; - import static io.anuke.mindustry.Vars.bulletGroup; -public class Lightning extends TimedEntity implements DrawTrait, SyncTrait, TimeTrait{ +public class Lightning extends TimedEntity implements DrawTrait, TimeTrait{ public static final float lifetime = 10f; private static final RandomXS128 random = new RandomXS128(); @@ -91,19 +89,6 @@ public class Lightning extends TimedEntity implements DrawTrait, SyncTrait, Time } } - @Override - public boolean isSyncing(){ - return false; - } - - @Override - public void write(DataOutput data){ - } - - @Override - public void read(DataInput data){ - } - @Override public float lifetime(){ return lifetime; diff --git a/core/src/io/anuke/mindustry/entities/effect/Puddle.java b/core/src/io/anuke/mindustry/entities/effect/Puddle.java index 4b633ac41d..b9885f5a20 100644 --- a/core/src/io/anuke/mindustry/entities/effect/Puddle.java +++ b/core/src/io/anuke/mindustry/entities/effect/Puddle.java @@ -16,6 +16,7 @@ import io.anuke.mindustry.content.*; import io.anuke.mindustry.entities.*; import io.anuke.mindustry.entities.impl.SolidEntity; import io.anuke.mindustry.entities.traits.*; +import io.anuke.mindustry.game.TypeID; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.type.Liquid; @@ -143,6 +144,11 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai return liquid.flammability * amount; } + @Override + public TypeID getTypeID(){ + return TypeIDs.puddle; + } + @Override public byte version(){ return 0; @@ -280,7 +286,9 @@ public class Puddle extends SolidEntity implements SaveTrait, Poolable, DrawTrai @Override public void removed(){ - map.remove(tile.pos()); + if(tile != null){ + map.remove(tile.pos()); + } reset(); } diff --git a/core/src/io/anuke/mindustry/entities/effect/RubbleDecal.java b/core/src/io/anuke/mindustry/entities/effect/RubbleDecal.java index 7944714f6b..8f2fb733ef 100644 --- a/core/src/io/anuke/mindustry/entities/effect/RubbleDecal.java +++ b/core/src/io/anuke/mindustry/entities/effect/RubbleDecal.java @@ -8,22 +8,14 @@ import io.anuke.arc.math.Mathf; import static io.anuke.mindustry.Vars.headless; public class RubbleDecal extends Decal{ - private static final TextureRegion[][] regions = new TextureRegion[16][0]; private TextureRegion region; /** Creates a rubble effect at a position. Provide a block size to use. */ public static void create(float x, float y, int size){ if(headless) return; - if(regions[size].length == 0 || regions[size][0].getTexture().isDisposed()){ - regions[size] = new TextureRegion[2]; - for(int j = 0; j < 2; j++){ - regions[size][j] = Core.atlas.find("rubble-" + size + "-" + j); - } - } - RubbleDecal decal = new RubbleDecal(); - decal.region = regions[size][Mathf.clamp(Mathf.randomSeed(decal.id, 0, 1), 0, regions[size].length - 1)]; + decal.region = Core.atlas.find("rubble-" + size + "-" + Mathf.randomSeed(decal.id, 0, 1)); if(!Core.atlas.isFound(decal.region)){ return; diff --git a/core/src/io/anuke/mindustry/entities/traits/BuilderMinerTrait.java b/core/src/io/anuke/mindustry/entities/traits/BuilderMinerTrait.java new file mode 100644 index 0000000000..5fbde29251 --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/traits/BuilderMinerTrait.java @@ -0,0 +1,22 @@ +package io.anuke.mindustry.entities.traits; + +/** A class for gracefully merging mining and building traits.*/ +public interface BuilderMinerTrait extends MinerTrait, BuilderTrait{ + + default void updateMechanics(){ + updateBuilding(); + + //mine only when not building + if(buildRequest() == null){ + updateMining(); + } + } + + default void drawMechanics(){ + if(isBuilding()){ + drawBuilding(); + }else{ + drawMining(); + } + } +} diff --git a/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java b/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java index d4d0e47560..595a094097 100644 --- a/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java +++ b/core/src/io/anuke/mindustry/entities/traits/BuilderTrait.java @@ -4,7 +4,6 @@ import io.anuke.arc.Core; import io.anuke.arc.Events; import io.anuke.arc.collection.Array; import io.anuke.arc.collection.Queue; -import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.math.Angles; import io.anuke.arc.math.Mathf; @@ -12,15 +11,12 @@ import io.anuke.arc.math.geom.Vector2; import io.anuke.arc.util.Time; import io.anuke.mindustry.Vars; import io.anuke.mindustry.content.Blocks; -import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.Effects; -import io.anuke.mindustry.entities.type.*; +import io.anuke.mindustry.entities.type.TileEntity; +import io.anuke.mindustry.entities.type.Unit; import io.anuke.mindustry.game.EventType.BuildSelectEvent; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.graphics.Pal; -import io.anuke.mindustry.graphics.Shapes; import io.anuke.mindustry.net.Net; -import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.*; import io.anuke.mindustry.world.blocks.BuildBlock; import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity; @@ -32,72 +28,67 @@ import static io.anuke.mindustry.Vars.*; import static io.anuke.mindustry.entities.traits.BuilderTrait.BuildDataStatic.removal; import static io.anuke.mindustry.entities.traits.BuilderTrait.BuildDataStatic.tmptr; -/** - * Interface for units that build, break or mine things. - */ +/** Interface for units that build things.*/ public interface BuilderTrait extends Entity, TeamTrait{ //these are not instance variables! float placeDistance = 220f; float mineDistance = 70f; - /** - * Update building mechanism for this unit. - * This includes mining. - */ + /** Updates building mechanism for this unit.*/ default void updateBuilding(){ float finalPlaceDst = state.rules.infiniteResources ? Float.MAX_VALUE : placeDistance; Unit unit = (Unit)this; //remove already completed build requests removal.clear(); - for(BuildRequest req : getPlaceQueue()){ + for(BuildRequest req : buildQueue()){ removal.add(req); } - getPlaceQueue().clear(); + buildQueue().clear(); for(BuildRequest request : removal){ - if(!((request.breaking && world.tile(request.x, request.y).block() == Blocks.air) || - (!request.breaking && (world.tile(request.x, request.y).rotation() == request.rotation || !request.block.rotate) - && world.tile(request.x, request.y).block() == request.block))){ - getPlaceQueue().addLast(request); + Tile tile = world.tile(request.x, request.y); + + if(!(tile == null || (request.breaking && tile.block() == Blocks.air) || + (!request.breaking && (tile.rotation() == request.rotation || !request.block.rotate) && tile.block() == request.block))){ + buildQueue().addLast(request); } } - BuildRequest current = getCurrentRequest(); + BuildRequest current = buildRequest(); - //update mining here if(current == null){ - if(getMineTile() != null){ - updateMining(); - } return; - }else{ - setMineTile(null); } Tile tile = world.tile(current.x, current.y); if(dst(tile) > finalPlaceDst){ - if(getPlaceQueue().size > 1){ - getPlaceQueue().removeFirst(); - getPlaceQueue().addLast(current); + if(buildQueue().size > 1){ + buildQueue().removeFirst(); + buildQueue().addLast(current); } return; } if(!(tile.block() instanceof BuildBlock)){ - if(canCreateBlocks() && !current.breaking && Build.validPlace(getTeam(), current.x, current.y, current.block, current.rotation)){ + if(!current.initialized && canCreateBlocks() && !current.breaking && Build.validPlace(getTeam(), current.x, current.y, current.block, current.rotation)){ Call.beginPlace(getTeam(), current.x, current.y, current.block, current.rotation); - }else if(canCreateBlocks() && current.breaking && Build.validBreak(getTeam(), current.x, current.y)){ + }else if(!current.initialized && canCreateBlocks() && current.breaking && Build.validBreak(getTeam(), current.x, current.y)){ Call.beginBreak(getTeam(), current.x, current.y); }else{ - getPlaceQueue().removeFirst(); + buildQueue().removeFirst(); return; } } TileEntity core = unit.getClosestCore(); + if(tile.entity instanceof BuildEntity && !current.initialized){ + Core.app.post(() -> Events.fire(new BuildSelectEvent(tile, unit.getTeam(), this, current.breaking))); + current.initialized = true; + } + //if there is no core to build with or no build entity, stop building! if((core == null && !state.rules.infiniteResources) || !(tile.entity instanceof BuildEntity)){ return; @@ -127,38 +118,21 @@ public interface BuilderTrait extends Entity, TeamTrait{ }else{ entity.progress = current.progress; } - - if(!current.initialized){ - Core.app.post(() -> Events.fire(new BuildSelectEvent(tile, unit.getTeam(), this, current.breaking))); - current.initialized = true; - } } /** Returns the queue for storing build requests. */ - Queue getPlaceQueue(); - - /** Returns the tile this builder is currently mining. */ - Tile getMineTile(); - - /** Sets the tile this builder is currently mining. */ - void setMineTile(Tile tile); - - /** Returns the minining speed of this miner. 1 = standard, 0.5 = half speed, 2 = double speed, etc. */ - float getMinePower(); + Queue buildQueue(); /** Build power, can be any float. 1 = builds recipes in normal time, 0 = doesn't build at all. */ float getBuildPower(Tile tile); - /** Returns whether or not this builder can mine a specific item type. */ - boolean canMine(Item item); - /** Whether this type of builder can begin creating new blocks. */ default boolean canCreateBlocks(){ return true; } default void writeBuilding(DataOutput output) throws IOException{ - BuildRequest request = getCurrentRequest(); + BuildRequest request = buildRequest(); if(request != null){ output.writeByte(request.breaking ? 1 : 0); @@ -178,7 +152,7 @@ public interface BuilderTrait extends Entity, TeamTrait{ } default void readBuilding(DataInput input, boolean applyChanges) throws IOException{ - if(applyChanges) getPlaceQueue().clear(); + if(applyChanges) buildQueue().clear(); byte type = input.readByte(); if(type != -1){ @@ -197,26 +171,26 @@ public interface BuilderTrait extends Entity, TeamTrait{ request.progress = progress; if(applyChanges){ - getPlaceQueue().addLast(request); + buildQueue().addLast(request); }else if(isBuilding()){ - getCurrentRequest().progress = progress; + buildRequest().progress = progress; } } } /** Return whether this builder's place queue contains items. */ default boolean isBuilding(){ - return getPlaceQueue().size != 0; + return buildQueue().size != 0; } /** Clears the placement queue. */ default void clearBuilding(){ - getPlaceQueue().clear(); + buildQueue().clear(); } /** Add another build requests to the tail of the queue, if it doesn't exist there yet. */ default void addBuildRequest(BuildRequest place){ - for(BuildRequest request : getPlaceQueue()){ + for(BuildRequest request : buildQueue()){ if(request.x == place.x && request.y == place.y){ return; } @@ -225,71 +199,29 @@ public interface BuilderTrait extends Entity, TeamTrait{ if(tile != null && tile.entity instanceof BuildEntity){ place.progress = tile.entity().progress; } - getPlaceQueue().addLast(place); + buildQueue().addLast(place); } /** * Return the build requests currently active, or the one at the top of the queue. * May return null. */ - default BuildRequest getCurrentRequest(){ - return getPlaceQueue().size == 0 ? null : getPlaceQueue().first(); + default BuildRequest buildRequest(){ + return buildQueue().size == 0 ? null : buildQueue().first(); } - //due to iOS wierdness, this is apparently required + //due to iOS weirdness, this is apparently required class BuildDataStatic{ static Array removal = new Array<>(); static Vector2[] tmptr = new Vector2[]{new Vector2(), new Vector2(), new Vector2(), new Vector2()}; } - /** Do not call directly. */ - default void updateMining(){ - Unit unit = (Unit)this; - Tile tile = getMineTile(); - TileEntity core = unit.getClosestCore(); - - if(core == null || tile.block() != Blocks.air || dst(tile.worldx(), tile.worldy()) > mineDistance - || tile.drop() == null || !unit.acceptsItem(tile.drop()) || !canMine(tile.drop())){ - setMineTile(null); - }else{ - 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())){ - - if(unit.dst(core) < mineTransferRange && core.tile.block().acceptStack(item, 1, core.tile, unit) == 1){ - Call.transferItemTo(item, 1, - tile.worldx() + Mathf.range(tilesize / 2f), - tile.worldy() + Mathf.range(tilesize / 2f), core.tile); - }else if(unit.acceptsItem(item)){ - Call.transferItemToUnit(item, - tile.worldx() + Mathf.range(tilesize / 2f), - tile.worldy() + Mathf.range(tilesize / 2f), - unit); - } - } - - if(Mathf.chance(0.06 * Time.delta())){ - Effects.effect(Fx.pulverizeSmall, - tile.worldx() + Mathf.range(tilesize / 2f), - tile.worldy() + Mathf.range(tilesize / 2f), 0f, item.color); - } - } - } - - /** Draw placement effects for an entity. This includes mining */ + /** Draw placement effects for an entity. */ default void drawBuilding(){ + if(!isBuilding()) return; + Unit unit = (Unit)this; - BuildRequest request; - if(!isBuilding()){ - if(getMineTile() != null){ - drawMining(); - } - return; - } - - request = getCurrentRequest(); - + BuildRequest request = buildRequest(); Tile tile = world.tile(request.x, request.y); if(dst(tile) > placeDistance && !state.isEditor()){ @@ -310,10 +242,10 @@ public interface BuilderTrait extends Entity, TeamTrait{ tmptr[3].set(tile.drawx() + sz, tile.drawy() + sz); Arrays.sort(tmptr, (a, b) -> -Float.compare(Angles.angleDist(Angles.angle(unit.x, unit.y, a.x, a.y), ang), - Angles.angleDist(Angles.angle(unit.x, unit.y, b.x, b.y), ang))); + Angles.angleDist(Angles.angle(unit.x, unit.y, b.x, b.y), ang))); float x1 = tmptr[0].x, y1 = tmptr[0].y, - x3 = tmptr[1].x, y3 = tmptr[1].y; + x3 = tmptr[1].x, y3 = tmptr[1].y; Draw.alpha(1f); @@ -325,35 +257,6 @@ public interface BuilderTrait extends Entity, TeamTrait{ Draw.color(); } - /** Internal use only. */ - default void drawMining(){ - Unit unit = (Unit)this; - Tile tile = getMineTile(); - - if(tile == null) return; - - float focusLen = 4f + Mathf.absin(Time.time(), 1.1f, 0.5f); - float swingScl = 12f, swingMag = tilesize / 8f; - float flashScl = 0.3f; - - float px = unit.x + Angles.trnsx(unit.rotation, focusLen); - float py = unit.y + Angles.trnsy(unit.rotation, focusLen); - - float ex = tile.worldx() + Mathf.sin(Time.time() + 48, swingScl, swingMag); - float ey = tile.worldy() + Mathf.sin(Time.time() + 48, swingScl + 2f, swingMag); - - Draw.color(Color.LIGHT_GRAY, Color.WHITE, 1f - flashScl + Mathf.absin(Time.time(), 0.5f, flashScl)); - - Shapes.laser("minelaser", "minelaser-end", px, py, ex, ey, 0.75f); - - if(unit instanceof Player && ((Player)unit).isLocal){ - Lines.stroke(1f, Pal.accent); - Lines.poly(tile.worldx(), tile.worldy(), 4, tilesize / 2f * Mathf.sqrt2, Time.time()); - } - - Draw.color(); - } - /** Class for storing build requests. Can be either a place or remove request. */ class BuildRequest{ public final int x, y, rotation; diff --git a/core/src/io/anuke/mindustry/entities/traits/MinerTrait.java b/core/src/io/anuke/mindustry/entities/traits/MinerTrait.java new file mode 100644 index 0000000000..da2f0fcfc9 --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/traits/MinerTrait.java @@ -0,0 +1,102 @@ +package io.anuke.mindustry.entities.traits; + +import io.anuke.arc.Core; +import io.anuke.arc.graphics.Color; +import io.anuke.arc.graphics.g2d.*; +import io.anuke.arc.math.*; +import io.anuke.arc.util.Time; +import io.anuke.mindustry.content.*; +import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.type.*; +import io.anuke.mindustry.gen.Call; +import io.anuke.mindustry.graphics.*; +import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.world.Tile; + +import static io.anuke.mindustry.Vars.*; + +public interface MinerTrait extends Entity{ + + /** Returns the range at which this miner can mine blocks.*/ + default float getMiningRange(){ + return 70f; + } + + default boolean isMining(){ + return getMineTile() != null; + } + + /** Returns the tile this builder is currently mining. */ + Tile getMineTile(); + + /** Sets the tile this builder is currently mining. */ + void setMineTile(Tile tile); + + /** Returns the mining speed of this miner. 1 = standard, 0.5 = half speed, 2 = double speed, etc. */ + float getMinePower(); + + /** Returns whether or not this builder can mine a specific item type. */ + boolean canMine(Item item); + + default void updateMining(){ + Unit unit = (Unit)this; + Tile tile = getMineTile(); + TileEntity core = unit.getClosestCore(); + + if(tile == null || core == null || tile.block() != Blocks.air || dst(tile.worldx(), tile.worldy()) > getMiningRange() + || tile.drop() == null || !unit.acceptsItem(tile.drop()) || !canMine(tile.drop())){ + setMineTile(null); + }else{ + 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())){ + + if(unit.dst(core) < mineTransferRange && core.tile.block().acceptStack(item, 1, core.tile, unit) == 1){ + Call.transferItemTo(item, 1, + tile.worldx() + Mathf.range(tilesize / 2f), + tile.worldy() + Mathf.range(tilesize / 2f), core.tile); + }else if(unit.acceptsItem(item)){ + Call.transferItemToUnit(item, + tile.worldx() + Mathf.range(tilesize / 2f), + tile.worldy() + Mathf.range(tilesize / 2f), + unit); + } + } + + if(Mathf.chance(0.06 * Time.delta())){ + Effects.effect(Fx.pulverizeSmall, + tile.worldx() + Mathf.range(tilesize / 2f), + tile.worldy() + Mathf.range(tilesize / 2f), 0f, item.color); + } + } + } + + default void drawMining(){ + Unit unit = (Unit)this; + Tile tile = getMineTile(); + + if(tile == null) return; + + float focusLen = 4f + Mathf.absin(Time.time(), 1.1f, 0.5f); + float swingScl = 12f, swingMag = tilesize / 8f; + float flashScl = 0.3f; + + float px = unit.x + Angles.trnsx(unit.rotation, focusLen); + float py = unit.y + Angles.trnsy(unit.rotation, focusLen); + + float ex = tile.worldx() + Mathf.sin(Time.time() + 48, swingScl, swingMag); + float ey = tile.worldy() + Mathf.sin(Time.time() + 48, swingScl + 2f, swingMag); + + Draw.color(Color.LIGHT_GRAY, Color.WHITE, 1f - flashScl + Mathf.absin(Time.time(), 0.5f, flashScl)); + + Shapes.laser(Core.atlas.find("minelaser"), Core.atlas.find("minelaser-end"), px, py, ex, ey, 0.75f); + + if(unit instanceof Player && ((Player)unit).isLocal){ + Lines.stroke(1f, Pal.accent); + Lines.poly(tile.worldx(), tile.worldy(), 4, tilesize / 2f * Mathf.sqrt2, Time.time()); + } + + Draw.color(); + } +} diff --git a/core/src/io/anuke/mindustry/entities/traits/TypeTrait.java b/core/src/io/anuke/mindustry/entities/traits/TypeTrait.java index 69d1794e96..9e53f9678a 100644 --- a/core/src/io/anuke/mindustry/entities/traits/TypeTrait.java +++ b/core/src/io/anuke/mindustry/entities/traits/TypeTrait.java @@ -1,17 +1,18 @@ package io.anuke.mindustry.entities.traits; -import io.anuke.arc.collection.Array; -import io.anuke.arc.collection.ObjectIntMap; -import io.anuke.arc.function.Supplier; +import io.anuke.mindustry.game.TypeID; public interface TypeTrait{ + + TypeID getTypeID(); + /* int[] lastRegisteredID = {0}; Array> registeredTypes = new Array<>(); ObjectIntMap> typeToID = new ObjectIntMap<>(); /** * Register and return a type ID. The supplier should return a fresh instace of that type. - */ + static void registerType(Class type, Supplier supplier){ if(typeToID.get(type, -1) != -1){ return; //already registered @@ -23,7 +24,7 @@ public interface TypeTrait{ lastRegisteredID[0]++; } - /**Gets a syncable type by ID.*/ + /**Gets a syncable type by ID. static Supplier getTypeByID(int id){ if(id == -1){ throw new IllegalArgumentException("Attempt to retrieve invalid entity type ID! Did you forget to set it in ContentLoader.registerTypes()?"); @@ -34,11 +35,11 @@ public interface TypeTrait{ /** * Returns the type ID of this entity used for intstantiation. Should be < BYTE_MAX. * Do not override! - */ + default int getTypeID(){ int id = typeToID.get(getClass(), -1); if(id == -1) throw new RuntimeException("Class of type '" + getClass() + "' is not registered! Did you forget to register it in ContentLoader#registerTypes()?"); return id; - } + }*/ } diff --git a/core/src/io/anuke/mindustry/entities/type/BaseUnit.java b/core/src/io/anuke/mindustry/entities/type/BaseUnit.java index 334b21db3c..a8dd3b5670 100644 --- a/core/src/io/anuke/mindustry/entities/type/BaseUnit.java +++ b/core/src/io/anuke/mindustry/entities/type/BaseUnit.java @@ -1,7 +1,6 @@ package io.anuke.mindustry.entities.type; -import io.anuke.annotations.Annotations.Loc; -import io.anuke.annotations.Annotations.Remote; +import io.anuke.annotations.Annotations.*; import io.anuke.arc.Core; import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.graphics.g2d.TextureRegion; @@ -19,6 +18,7 @@ import io.anuke.mindustry.entities.traits.ShooterTrait; import io.anuke.mindustry.entities.traits.TargetTrait; import io.anuke.mindustry.entities.units.*; import io.anuke.mindustry.game.Team; +import io.anuke.mindustry.game.TypeID; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.net.Net; import io.anuke.mindustry.type.*; @@ -80,6 +80,15 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ return type.drag; } + @Override + public TypeID getTypeID(){ + return type.typeID; + } + + public @Nullable Tile getSpawner(){ + return world.tile(spawner); + } + /** Initialize the type and team of this unit. Only call once! */ public void init(UnitType type, Team team){ if(this.type != null) throw new RuntimeException("This unit is already initialized!"); @@ -101,17 +110,16 @@ public abstract class BaseUnit extends Unit implements ShooterTrait{ } public boolean targetHasFlag(BlockFlag flag){ - return target instanceof TileEntity && ((TileEntity)target).tile.block().flags.contains(flag); + return (target instanceof TileEntity && ((TileEntity)target).tile.block().flags.contains(flag)) || + (target instanceof Tile && ((Tile)target).block().flags.contains(flag)); } public void setState(UnitState state){ this.state.set(state); } - public void retarget(Runnable run){ - if(timer.get(timerTarget, 20)){ - run.run(); - } + public boolean retarget(){ + return timer.get(timerTarget, 20); } /** Only runs when the unit has a target. */ diff --git a/core/src/io/anuke/mindustry/entities/type/FlyingUnit.java b/core/src/io/anuke/mindustry/entities/type/FlyingUnit.java index dc92379241..6620f20c60 100644 --- a/core/src/io/anuke/mindustry/entities/type/FlyingUnit.java +++ b/core/src/io/anuke/mindustry/entities/type/FlyingUnit.java @@ -32,7 +32,7 @@ public abstract class FlyingUnit extends BaseUnit{ target = null; } - retarget(() -> { + if(retarget()){ targetClosest(); if(target == null) targetClosestEnemyFlag(BlockFlag.producer); @@ -41,7 +41,7 @@ public abstract class FlyingUnit extends BaseUnit{ if(target == null){ setState(patrol); } - }); + } if(target != null){ attack(type.attackLength); @@ -71,7 +71,7 @@ public abstract class FlyingUnit extends BaseUnit{ }, patrol = new UnitState(){ public void update(){ - retarget(() -> { + if(retarget()){ targetClosest(); targetClosestEnemyFlag(BlockFlag.target); @@ -81,7 +81,7 @@ public abstract class FlyingUnit extends BaseUnit{ } target = getClosestCore(); - }); + }; if(target != null){ circle(60f + Mathf.absin(Time.time() + Mathf.randomSeed(id) * 1200f, 70f, 1200f)); diff --git a/core/src/io/anuke/mindustry/entities/type/GroundUnit.java b/core/src/io/anuke/mindustry/entities/type/GroundUnit.java index 0239f9bdf2..e319063e9d 100644 --- a/core/src/io/anuke/mindustry/entities/type/GroundUnit.java +++ b/core/src/io/anuke/mindustry/entities/type/GroundUnit.java @@ -176,7 +176,9 @@ public abstract class GroundUnit extends BaseUnit{ target = null; } - retarget(this::targetClosest); + if(retarget()){ + targetClosest(); + } } protected void patrol(){ diff --git a/core/src/io/anuke/mindustry/entities/type/Player.java b/core/src/io/anuke/mindustry/entities/type/Player.java index 41f98ef021..91db0f1122 100644 --- a/core/src/io/anuke/mindustry/entities/type/Player.java +++ b/core/src/io/anuke/mindustry/entities/type/Player.java @@ -12,11 +12,11 @@ import io.anuke.arc.math.geom.*; import io.anuke.arc.util.*; import io.anuke.arc.util.pooling.Pools; import io.anuke.mindustry.Vars; -import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.content.Mechs; +import io.anuke.mindustry.content.*; import io.anuke.mindustry.entities.*; import io.anuke.mindustry.entities.traits.*; import io.anuke.mindustry.game.Team; +import io.anuke.mindustry.game.TypeID; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.input.Binding; @@ -33,7 +33,7 @@ import java.io.*; import static io.anuke.mindustry.Vars.*; -public class Player extends Unit implements BuilderTrait, ShooterTrait{ +public class Player extends Unit implements BuilderMinerTrait, ShooterTrait{ public static final int timerSync = 2; public static final int timerAbility = 3; private static final int timerShootLeft = 0; @@ -115,6 +115,11 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ heal(); } + @Override + public TypeID getTypeID(){ + return TypeIDs.player; + } + @Override public void move(float x, float y){ if(!mech.flying){ @@ -241,7 +246,7 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ } @Override - public Queue getPlaceQueue(){ + public Queue buildQueue(){ return placeQueue; } @@ -362,7 +367,7 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ public void drawOver(){ if(dead) return; - drawBuilding(); + drawMechanics(); } @Override @@ -428,8 +433,8 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ /** Draw all current build requests. Does not draw the beam effect, only the positions. */ public void drawBuildRequests(){ BuildRequest last = null; - for(BuildRequest request : getPlaceQueue()){ - if(getCurrentRequest() == request && request.progress > 0.001f) continue; + for(BuildRequest request : buildQueue()){ + if(request.progress > 0.01f || (buildRequest() == request && (dst(request.x * tilesize, request.y * tilesize) <= placeDistance || state.isEditor()))) continue; if(request.breaking){ Block block = world.ltile(request.x, request.y).block(); @@ -551,7 +556,7 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ if(!isLocal){ interpolate(); - updateBuilding(); //building happens even with non-locals + updateMechanics(); //building happens even with non-locals status.update(this); //status effect updating also happens with non locals for effect purposes updateVelocityStatus(); //velocity too, for visual purposes @@ -564,22 +569,22 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ data.unlockContent(mech); } - if(mobile){ - updateFlying(); + if(mobile && !Core.settings.getBool("keyboard")){ + updateTouch(); }else{ - updateMech(); + updateKeyboard(); } isTyping = ui.chatfrag.chatOpen(); - updateBuilding(); + updateMechanics(); if(!mech.flying){ clampPosition(); } } - protected void updateMech(){ + protected void updateKeyboard(){ Tile tile = world.tileWorld(x, y); isBoosting = Core.input.keyDown(Binding.dash) && !mech.flying; @@ -646,7 +651,7 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ } } - protected void updateFlying(){ + protected void updateTouch(){ if(Units.invalidateTarget(target, this) && !(target instanceof TileEntity && ((TileEntity)target).damaged() && target.isValid() && target.getTeam() == team && mech.canHeal && dst(target) < getWeapon().bullet.range())){ target = null; } @@ -657,6 +662,7 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ float targetX = Core.camera.position.x, targetY = Core.camera.position.y; float attractDst = 15f; + float speed = isBoosting && !mech.flying ? mech.boostSpeed : mech.speed; if(moveTarget != null && !moveTarget.isDead()){ targetX = moveTarget.getX(); @@ -669,7 +675,7 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ } if(dst(moveTarget) <= 2f * Time.delta()){ - if(tapping){ + if(tapping && !isDead()){ Tile tile = ((TileEntity)moveTarget).tile; tile.block().tapped(tile, this); } @@ -680,7 +686,7 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ moveTarget = null; } - movement.set((targetX - x) / Time.delta(), (targetY - y) / Time.delta()).limit(isBoosting && !mech.flying ? mech.boostSpeed : mech.speed); + movement.set((targetX - x) / Time.delta(), (targetY - y) / Time.delta()).limit(speed); movement.setAngle(Mathf.slerp(movement.angle(), velocity.angle(), 0.05f)); if(dst(targetX, targetY) < attractDst){ @@ -855,13 +861,13 @@ public class Player extends Unit implements BuilderTrait, ShooterTrait{ byte mechid = stream.readByte(); int spawner = stream.readInt(); Tile stile = world.tile(spawner); - if(stile != null && stile.entity instanceof SpawnerTrait){ - lastSpawner = (SpawnerTrait)stile.entity; - } Player player = headless ? this : Vars.player; player.readSaveSuper(stream, version); player.mech = content.getByID(ContentType.mech, mechid); player.dead = false; + if(stile != null && stile.entity instanceof SpawnerTrait){ + player.lastSpawner = (SpawnerTrait)stile.entity; + } } } diff --git a/core/src/io/anuke/mindustry/entities/type/Unit.java b/core/src/io/anuke/mindustry/entities/type/Unit.java index 1eb1b48269..b36e8dde83 100644 --- a/core/src/io/anuke/mindustry/entities/type/Unit.java +++ b/core/src/io/anuke/mindustry/entities/type/Unit.java @@ -265,6 +265,15 @@ public abstract class Unit extends DestructibleEntity implements SaveTrait, Targ } } + //repel player out of bounds + final float warpDst = 180f; + + if(x < 0) velocity.x += (-x/warpDst); + if(y < 0) velocity.y += (-y/warpDst); + if(x > world.unitWidth()) velocity.x -= (x - world.unitWidth())/warpDst; + if(y > world.unitHeight()) velocity.y -= (y - world.unitHeight())/warpDst; + + if(isFlying()){ drownTime = 0f; move(velocity.x * Time.delta(), velocity.y * Time.delta()); diff --git a/core/src/io/anuke/mindustry/entities/type/base/BaseDrone.java b/core/src/io/anuke/mindustry/entities/type/base/BaseDrone.java new file mode 100644 index 0000000000..0ce42b0bc1 --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/type/base/BaseDrone.java @@ -0,0 +1,59 @@ +package io.anuke.mindustry.entities.type.base; + +import io.anuke.arc.math.Mathf; +import io.anuke.arc.math.geom.Geometry; +import io.anuke.mindustry.entities.type.FlyingUnit; +import io.anuke.mindustry.entities.units.UnitState; +import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.meta.BlockFlag; + +import static io.anuke.mindustry.Vars.world; + +public abstract class BaseDrone extends FlyingUnit{ + public final UnitState retreat = new UnitState(){ + public void entered(){ + target = null; + } + + public void update(){ + if(health >= maxHealth()){ + state.set(getStartState()); + }else if(!targetHasFlag(BlockFlag.repair)){ + if(retarget()){ + Tile repairPoint = Geometry.findClosest(x, y, world.indexer.getAllied(team, BlockFlag.repair)); + if(repairPoint != null){ + target = repairPoint; + }else{ + setState(getStartState()); + } + } + }else{ + circle(40f); + } + } + }; + + @Override + protected void updateRotation(){ + if(target != null && shouldRotate() && target.dst(this) < type.range){ + rotation = Mathf.slerpDelta(rotation, angleTo(target), 0.3f); + }else{ + rotation = Mathf.slerpDelta(rotation, velocity.angle(), 0.3f); + } + } + + @Override + public void behavior(){ + if(health <= maxHealth() * type.retreatPercent && !state.is(retreat) && Geometry.findClosest(x, y, world.indexer.getAllied(team, BlockFlag.repair)) != null){ + setState(retreat); + } + } + + public boolean shouldRotate(){ + return state.is(getStartState()); + } + + @Override + public abstract UnitState getStartState(); + +} diff --git a/core/src/io/anuke/mindustry/entities/type/base/BuilderDrone.java b/core/src/io/anuke/mindustry/entities/type/base/BuilderDrone.java new file mode 100644 index 0000000000..21649dbf07 --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/type/base/BuilderDrone.java @@ -0,0 +1,241 @@ +package io.anuke.mindustry.entities.type.base; + +import io.anuke.arc.Core; +import io.anuke.arc.Events; +import io.anuke.arc.collection.IntIntMap; +import io.anuke.arc.collection.Queue; +import io.anuke.arc.math.Mathf; +import io.anuke.arc.util.*; +import io.anuke.mindustry.Vars; +import io.anuke.mindustry.entities.EntityGroup; +import io.anuke.mindustry.entities.traits.BuilderTrait; +import io.anuke.mindustry.entities.traits.TargetTrait; +import io.anuke.mindustry.entities.type.*; +import io.anuke.mindustry.entities.units.UnitState; +import io.anuke.mindustry.game.EventType.BuildSelectEvent; +import io.anuke.mindustry.game.Teams.TeamData; +import io.anuke.mindustry.gen.BrokenBlock; +import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.blocks.BuildBlock; +import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity; + +import java.io.*; + +import static io.anuke.mindustry.Vars.*; + +public class BuilderDrone extends BaseDrone implements BuilderTrait{ + private static final StaticReset reset = new StaticReset(); + private static final IntIntMap totals = new IntIntMap(); + + protected Queue placeQueue = new Queue<>(); + protected boolean isBreaking; + protected Player playerTarget; + + public final UnitState + + build = new UnitState(){ + + public void entered(){ + if(!(target instanceof BuildEntity)){ + target = null; + } + } + + public void update(){ + BuildEntity entity = (BuildEntity)target; + TileEntity core = getClosestCore(); + + if(isBuilding() && entity == null && isRebuild()){ + target = world.tile(buildRequest().x, buildRequest().y); + circle(placeDistance * 0.7f); + target = null; + + BuildRequest request = buildRequest(); + + if(world.tile(request.x, request.y).entity instanceof BuildEntity){ + target = world.tile(request.x, request.y).entity; + } + }else if(entity != null && core != null && (entity.progress < 1f || entity.progress > 0f) && entity.tile.block() instanceof BuildBlock){ //building is valid + if(!isBuilding() && dst(target) < placeDistance * 0.9f){ //within distance, begin placing + if(isBreaking){ + buildQueue().addLast(new BuildRequest(entity.tile.x, entity.tile.y)); + }else{ + buildQueue().addLast(new BuildRequest(entity.tile.x, entity.tile.y, entity.tile.rotation(), entity.cblock)); + } + } + + circle(placeDistance * 0.7f); + velocity.scl(0.74f); + }else{ //else, building isn't valid, follow a player + target = null; + + if(playerTarget == null || playerTarget.getTeam() != team || !playerTarget.isValid()){ + playerTarget = null; + + if(retarget()){ + float minDst = Float.POSITIVE_INFINITY; + int minDrones = Integer.MAX_VALUE; + + //find player with min amount of drones + for(Player player : playerGroup.all()){ + if(player.getTeam() == team){ + int drones = getDrones(player); + float dst = dst2(player); + + if(playerTarget == null || drones < minDrones || (drones == minDrones && dst < minDst)){ + minDrones = drones; + minDst = dst; + playerTarget = player; + } + } + } + } + + if(getSpawner() != null){ + target = getSpawner(); + circle(40f); + target = null; + } + }else{ + incDrones(playerTarget); + TargetTrait prev = target; + target = playerTarget; + float dst = 90f + (id % 4)*30; + float tdst = dst(target); + float scale = (Mathf.lerp(1f, 0.77f, 1f - Mathf.clamp((tdst - dst) / dst))); + circle(dst); + velocity.scl(scale); + target = prev; + } + } + } + }; + + public BuilderDrone(){ + if(reset.check()){ + Events.on(BuildSelectEvent.class, event -> { + EntityGroup group = unitGroups[event.team.ordinal()]; + + if(!(event.tile.entity instanceof BuildEntity)) return; + + for(BaseUnit unit : group.all()){ + if(unit instanceof BuilderDrone){ + BuilderDrone drone = (BuilderDrone)unit; + if(drone.isBuilding()){ + //stop building if opposite building begins. + BuildRequest req = drone.buildRequest(); + if(req.breaking != event.breaking && req.x == event.tile.x && req.y == event.tile.y){ + drone.clearBuilding(); + drone.target = null; + } + } + } + } + }); + } + } + + int getDrones(Player player){ + return Pack.leftShort(totals.get(player.id, 0)); + } + + void incDrones(Player player){ + int num = totals.get(player.id, 0); + int amount = Pack.leftShort(num), frame = Pack.rightShort(num); + short curFrame = (short)(Core.graphics.getFrameId() % Short.MAX_VALUE); + + if(frame != curFrame){ + totals.put(player.id, Pack.shortInt((short)1, curFrame)); + }else{ + totals.put(player.id, Pack.shortInt((short)(amount + 1), curFrame)); + } + } + + boolean isRebuild(){ + //disabled until further notice, reason being that it's too annoying when playing enemies and too broken for ally use + return false; //Vars.state.rules.enemyCheat && team == waveTeam; + } + + @Override + public float getBuildPower(Tile tile){ + return type.buildPower; + } + + @Override + public Queue buildQueue(){ + return placeQueue; + } + + @Override + public void update(){ + super.update(); + + if(!isBuilding() && timer.get(timerTarget2, 15)){ + for(Player player : playerGroup.all()){ + if(player.getTeam() == team && player.buildRequest() != null){ + BuildRequest req = player.buildRequest(); + Tile tile = world.tile(req.x, req.y); + if(tile != null && tile.entity instanceof BuildEntity){ + BuildEntity b = tile.entity(); + float dist = Math.min(b.dst(x, y) - placeDistance, 0); + if(dist / type.maxVelocity < b.buildCost * 0.9f){ + target = b; + this.isBreaking = req.breaking; + setState(build); + break; + } + } + } + } + + if(isRebuild() && !isBuilding()){ + TeamData data = Vars.state.teams.get(team); + if(!data.brokenBlocks.isEmpty()){ + long block = data.brokenBlocks.removeLast(); + + placeQueue.addFirst(new BuildRequest(BrokenBlock.x(block), BrokenBlock.y(block), BrokenBlock.rotation(block), content.block(BrokenBlock.block(block)))); + setState(build); + } + } + } + + updateBuilding(); + } + + @Override + public boolean shouldRotate(){ + return isBuilding(); + } + + @Override + public UnitState getStartState(){ + return build; + } + + @Override + public void drawOver(){ + drawBuilding(); + } + + @Override + public float drawSize(){ + return isBuilding() ? placeDistance * 2f : 30f; + } + + @Override + public boolean canCreateBlocks(){ + return true; + } + + @Override + public void write(DataOutput data) throws IOException{ + super.write(data); + writeBuilding(data); + } + + @Override + public void read(DataInput data) throws IOException{ + super.read(data); + readBuilding(data); + } +} diff --git a/core/src/io/anuke/mindustry/entities/type/base/Draug.java b/core/src/io/anuke/mindustry/entities/type/base/Draug.java new file mode 100644 index 0000000000..47b7caed25 --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/type/base/Draug.java @@ -0,0 +1,4 @@ +package io.anuke.mindustry.entities.type.base; + +public class Draug extends MinerDrone{ +} diff --git a/core/src/io/anuke/mindustry/entities/type/base/Drone.java b/core/src/io/anuke/mindustry/entities/type/base/Drone.java deleted file mode 100644 index 6fd10ba022..0000000000 --- a/core/src/io/anuke/mindustry/entities/type/base/Drone.java +++ /dev/null @@ -1,366 +0,0 @@ -package io.anuke.mindustry.entities.type.base; - -import io.anuke.arc.Events; -import io.anuke.arc.collection.Queue; -import io.anuke.arc.math.Mathf; -import io.anuke.arc.math.geom.Geometry; -import io.anuke.arc.util.Structs; -import io.anuke.mindustry.content.Blocks; -import io.anuke.mindustry.entities.EntityGroup; -import io.anuke.mindustry.entities.Units; -import io.anuke.mindustry.entities.traits.BuilderTrait; -import io.anuke.mindustry.entities.type.*; -import io.anuke.mindustry.entities.units.UnitState; -import io.anuke.mindustry.game.EventType.BuildSelectEvent; -import io.anuke.mindustry.gen.Call; -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.type.ItemType; -import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.blocks.BuildBlock; -import io.anuke.mindustry.world.blocks.BuildBlock.BuildEntity; -import io.anuke.mindustry.world.meta.BlockFlag; - -import java.io.*; - -import static io.anuke.mindustry.Vars.*; - -public class Drone extends FlyingUnit implements BuilderTrait{ - - - protected Item targetItem; - protected Tile mineTile; - protected Queue placeQueue = new Queue<>(); - protected boolean isBreaking; - - public final UnitState - - build = new UnitState(){ - - public void entered(){ - if(!(target instanceof BuildEntity)){ - target = null; - } - } - - public void update(){ - BuildEntity entity = (BuildEntity)target; - TileEntity core = getClosestCore(); - - if(entity == null){ - setState(repair); - return; - } - - if(core == null) return; - - if((entity.progress < 1f || entity.progress > 0f) && entity.tile.block() instanceof BuildBlock){ //building is valid - if(!isBuilding() && dst(target) < placeDistance * 0.9f){ //within distance, begin placing - if(isBreaking){ - getPlaceQueue().addLast(new BuildRequest(entity.tile.x, entity.tile.y)); - }else{ - getPlaceQueue().addLast(new BuildRequest(entity.tile.x, entity.tile.y, entity.tile.rotation(), entity.cblock)); - } - } - - circle(placeDistance * 0.7f); - }else{ //building isn't valid - setState(repair); - } - } - }, - - repair = new UnitState(){ - - public void entered(){ - target = null; - } - - public void update(){ - - retarget(() -> { - target = Units.findDamagedTile(team, x, y); - - if(target == null){ - setState(mine); - } - }); - - if(target == null) return; - - if(target.dst(Drone.this) > type.range){ - circle(type.range * 0.9f); - }else{ - getWeapon().update(Drone.this, target.getX(), target.getY()); - } - } - }, - - mine = new UnitState(){ - public void entered(){ - target = null; - } - - public void update(){ - TileEntity entity = getClosestCore(); - - if(entity == null) return; - - if(targetItem == null){ - findItem(); - } - - //core full - if(targetItem != null && entity.block.acceptStack(targetItem, 1, entity.tile, Drone.this) == 0){ - setState(repair); - return; - } - - //if inventory is full, drop it off. - if(item.amount >= getItemCapacity()){ - setState(drop); - }else{ - if(targetItem != null && !acceptsItem(targetItem)){ - setState(drop); - return; - } - - retarget(() -> { - if(getMineTile() == null){ - findItem(); - } - - if(targetItem == null) return; - - target = world.indexer.findClosestOre(x, y, targetItem); - }); - - if(target instanceof Tile){ - moveTo(type.range / 1.5f); - - if(dst(target) < type.range && mineTile != target){ - setMineTile((Tile)target); - } - - if(((Tile)target).block() != Blocks.air){ - setState(drop); - } - } - } - } - - public void exited(){ - setMineTile(null); - } - }, - drop = new UnitState(){ - public void entered(){ - target = null; - } - - public void update(){ - if(item.amount == 0){ - setState(mine); - return; - } - - if(item.item.type != ItemType.material){ - item.amount = 0; - setState(mine); - return; - } - - target = getClosestCore(); - - if(target == null) return; - - TileEntity tile = (TileEntity)target; - - if(dst(target) < type.range){ - if(tile.tile.block().acceptStack(item.item, item.amount, tile.tile, Drone.this) == item.amount){ - Call.transferItemTo(item.item, item.amount, x, y, tile.tile); - item.amount = 0; - } - - setState(repair); - } - - circle(type.range / 1.8f); - } - }, - retreat = new UnitState(){ - public void entered(){ - target = null; - } - - public void update(){ - if(health >= maxHealth()){ - state.set(attack); - }else if(!targetHasFlag(BlockFlag.repair)){ - if(timer.get(timerTarget, 20)){ - Tile target = Geometry.findClosest(x, y, world.indexer.getAllied(team, BlockFlag.repair)); - if(target != null) Drone.this.target = target.entity; - } - }else{ - circle(40f); - } - } - }; - - static{ - - Events.on(BuildSelectEvent.class, event -> { - EntityGroup group = unitGroups[event.team.ordinal()]; - - if(!(event.tile.entity instanceof BuildEntity)) return; - - for(BaseUnit unit : group.all()){ - if(unit instanceof Drone){ - Drone drone = (Drone)unit; - if(drone.isBuilding()){ - //stop building if opposite building begins. - BuildRequest req = drone.getCurrentRequest(); - if(req.breaking != event.breaking && req.x == event.tile.x && req.y == event.tile.y){ - drone.clearBuilding(); - drone.setState(drone.repair); - } - } - } - } - }); - } - - @Override - public boolean canMine(Item item){ - return type.toMine.contains(item); - } - - @Override - public float getBuildPower(Tile tile){ - return type.buildPower; - } - - @Override - public float getMinePower(){ - return type.minePower; - } - - @Override - public Queue getPlaceQueue(){ - return placeQueue; - } - - @Override - public Tile getMineTile(){ - return mineTile; - } - - @Override - public void setMineTile(Tile tile){ - mineTile = tile; - } - - @Override - public void update(){ - super.update(); - - if(state.is(repair) && target != null && target.getTeam() != team){ - target = null; - } - - if(!state.is(build) && timer.get(timerTarget2, 15)){ - for(Player player : playerGroup.all()){ - if(player.getTeam() == team && player.getCurrentRequest() != null){ - BuildRequest req = player.getCurrentRequest(); - Tile tile = world.tile(req.x, req.y); - if(tile != null && tile.entity instanceof BuildEntity){ - BuildEntity b = tile.entity(); - float dist = Math.min(b.dst(x, y) - placeDistance, 0); - if(dist / type.maxVelocity < b.buildCost * 0.9f){ - target = b; - this.isBreaking = req.breaking; - setState(build); - break; - } - } - } - } - } - - updateBuilding(); - } - - @Override - protected void updateRotation(){ - if(target != null && ((state.is(repair) && target.dst(this) < type.range) || state.is(mine))){ - rotation = Mathf.slerpDelta(rotation, angleTo(target), 0.3f); - }else{ - rotation = Mathf.slerpDelta(rotation, velocity.angle(), 0.3f); - } - } - - @Override - public void behavior(){ - if(health <= health * type.retreatPercent && - Geometry.findClosest(x, y, world.indexer.getAllied(team, BlockFlag.repair)) != null){ - setState(retreat); - } - } - - @Override - public UnitState getStartState(){ - return repair; - } - - @Override - public void drawOver(){ - drawBuilding(); - } - - @Override - public float drawSize(){ - return isBuilding() ? placeDistance * 2f : 30f; - } - - protected void findItem(){ - TileEntity entity = getClosestCore(); - if(entity == null){ - return; - } - targetItem = Structs.findMin(type.toMine, world.indexer::hasOre, (a, b) -> -Integer.compare(entity.items.get(a), entity.items.get(b))); - } - - @Override - public boolean canCreateBlocks(){ - return true; - } - - @Override - public void write(DataOutput data) throws IOException{ - super.write(data); - data.writeInt(mineTile == null || !state.is(mine) ? -1 : mineTile.pos()); - data.writeInt(state.is(repair) && target instanceof TileEntity ? ((TileEntity)target).tile.pos() : -1); - writeBuilding(data); - } - - @Override - public void read(DataInput data) throws IOException{ - super.read(data); - int mined = data.readInt(); - int repairing = data.readInt(); - - readBuilding(data); - - if(mined != -1){ - mineTile = world.tile(mined); - } - - if(repairing != -1){ - Tile tile = world.tile(repairing); - target = tile.entity; - state.set(repair); - }else{ - state.set(retreat); - } - } - -} diff --git a/core/src/io/anuke/mindustry/entities/type/base/MinerDrone.java b/core/src/io/anuke/mindustry/entities/type/base/MinerDrone.java new file mode 100644 index 0000000000..450ed3cc34 --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/type/base/MinerDrone.java @@ -0,0 +1,179 @@ +package io.anuke.mindustry.entities.type.base; + +import io.anuke.arc.math.Mathf; +import io.anuke.arc.util.Structs; +import io.anuke.mindustry.content.Blocks; +import io.anuke.mindustry.entities.traits.MinerTrait; +import io.anuke.mindustry.entities.type.TileEntity; +import io.anuke.mindustry.entities.units.UnitState; +import io.anuke.mindustry.gen.Call; +import io.anuke.mindustry.type.Item; +import io.anuke.mindustry.type.ItemType; +import io.anuke.mindustry.world.Pos; +import io.anuke.mindustry.world.Tile; + +import java.io.*; + +import static io.anuke.mindustry.Vars.world; + +/** A drone that only mines.*/ +public class MinerDrone extends BaseDrone implements MinerTrait{ + protected Item targetItem; + protected Tile mineTile; + + public final UnitState + + mine = new UnitState(){ + public void entered(){ + target = null; + } + + public void update(){ + TileEntity entity = getClosestCore(); + + if(entity == null) return; + + findItem(); + + //core full of the target item, do nothing + if(targetItem != null && entity.block.acceptStack(targetItem, 1, entity.tile, MinerDrone.this) == 0){ + MinerDrone.this.clearItem(); + return; + } + + //if inventory is full, drop it off. + if(item.amount >= getItemCapacity() || (targetItem != null && !acceptsItem(targetItem))){ + setState(drop); + }else{ + if(retarget() && targetItem != null){ + target = world.indexer.findClosestOre(x, y, targetItem); + } + + if(target instanceof Tile){ + moveTo(type.range / 1.5f); + + if(dst(target) < type.range && mineTile != target){ + setMineTile((Tile)target); + } + + if(((Tile)target).block() != Blocks.air){ + setState(drop); + } + }else{ + //nothing to mine anymore, core full: circle spawnpoint + if(getSpawner() != null){ + target = getSpawner(); + + circle(40f); + } + } + } + } + + public void exited(){ + setMineTile(null); + } + }, + + drop = new UnitState(){ + public void entered(){ + target = null; + } + + public void update(){ + if(item.amount == 0 || item.item.type != ItemType.material){ + clearItem(); + setState(mine); + return; + } + + target = getClosestCore(); + + if(target == null) return; + + TileEntity tile = (TileEntity)target; + + if(dst(target) < type.range){ + if(tile.tile.block().acceptStack(item.item, item.amount, tile.tile, MinerDrone.this) > 0){ + Call.transferItemTo(item.item, item.amount, x, y, tile.tile); + } + + clearItem(); + setState(mine); + } + + circle(type.range / 1.8f); + } + }; + + @Override + public UnitState getStartState(){ + return mine; + } + + @Override + public void update(){ + super.update(); + + updateMining(); + } + + @Override + protected void updateRotation(){ + if(mineTile != null && shouldRotate() && mineTile.dst(this) < type.range){ + rotation = Mathf.slerpDelta(rotation, angleTo(mineTile), 0.3f); + }else{ + rotation = Mathf.slerpDelta(rotation, velocity.angle(), 0.3f); + } + } + + @Override + public boolean shouldRotate(){ + return isMining(); + } + + @Override + public void drawOver(){ + drawMining(); + } + + @Override + public boolean canMine(Item item){ + return type.toMine.contains(item); + } + + @Override + public float getMinePower(){ + return type.minePower; + } + + @Override + public Tile getMineTile(){ + return mineTile; + } + + @Override + public void setMineTile(Tile tile){ + mineTile = tile; + } + + @Override + public void write(DataOutput data) throws IOException{ + super.write(data); + data.writeInt(mineTile == null || !state.is(mine) ? Pos.invalid : mineTile.pos()); + } + + @Override + public void read(DataInput data) throws IOException{ + super.read(data); + mineTile = world.tile(data.readInt()); + } + + protected void findItem(){ + TileEntity entity = getClosestCore(); + if(entity == null){ + return; + } + targetItem = Structs.findMin(type.toMine, world.indexer::hasOre, (a, b) -> -Integer.compare(entity.items.get(a), entity.items.get(b))); + } +} diff --git a/core/src/io/anuke/mindustry/entities/type/base/Phantom.java b/core/src/io/anuke/mindustry/entities/type/base/Phantom.java index 516d305b94..1a50115647 100644 --- a/core/src/io/anuke/mindustry/entities/type/base/Phantom.java +++ b/core/src/io/anuke/mindustry/entities/type/base/Phantom.java @@ -1,5 +1,5 @@ package io.anuke.mindustry.entities.type.base; -public class Phantom extends Drone{ +public class Phantom extends BuilderDrone{ } diff --git a/core/src/io/anuke/mindustry/entities/type/base/RepairDrone.java b/core/src/io/anuke/mindustry/entities/type/base/RepairDrone.java new file mode 100644 index 0000000000..e5be4d3d07 --- /dev/null +++ b/core/src/io/anuke/mindustry/entities/type/base/RepairDrone.java @@ -0,0 +1,68 @@ +package io.anuke.mindustry.entities.type.base; + +import io.anuke.mindustry.entities.Units; +import io.anuke.mindustry.entities.type.TileEntity; +import io.anuke.mindustry.entities.units.UnitState; +import io.anuke.mindustry.world.Pos; +import io.anuke.mindustry.world.Tile; + +import java.io.*; + +import static io.anuke.mindustry.Vars.world; + +public class RepairDrone extends BaseDrone{ + public final UnitState repair = new UnitState(){ + + public void entered(){ + target = null; + } + + public void update(){ + + if(retarget()){ + target = Units.findDamagedTile(team, x, y); + } + + if(target != null){ + if(target.dst(RepairDrone.this) > type.range){ + circle(type.range * 0.9f); + }else{ + getWeapon().update(RepairDrone.this, target.getX(), target.getY()); + } + }else{ + //circle spawner if there's nothing to repair + if(getSpawner() != null){ + target = getSpawner(); + circle(type.range * 1.5f, type.speed/2f); + target = null; + } + } + } + }; + + @Override + public boolean shouldRotate(){ + return target != null; + } + + @Override + public UnitState getStartState(){ + return repair; + } + + @Override + public void write(DataOutput data) throws IOException{ + super.write(data); + data.writeInt(state.is(repair) && target instanceof TileEntity ? ((TileEntity)target).tile.pos() : Pos.invalid); + } + + @Override + public void read(DataInput data) throws IOException{ + super.read(data); + Tile repairing = world.tile(data.readInt()); + + if(repairing != null){ + target = repairing.entity; + } + } +} diff --git a/core/src/io/anuke/mindustry/entities/type/base/Spirit.java b/core/src/io/anuke/mindustry/entities/type/base/Spirit.java index f7142e8d6d..d43fc658b0 100644 --- a/core/src/io/anuke/mindustry/entities/type/base/Spirit.java +++ b/core/src/io/anuke/mindustry/entities/type/base/Spirit.java @@ -1,4 +1,4 @@ package io.anuke.mindustry.entities.type.base; -public class Spirit extends Drone{ +public class Spirit extends RepairDrone{ } diff --git a/core/src/io/anuke/mindustry/game/DefaultWaves.java b/core/src/io/anuke/mindustry/game/DefaultWaves.java index 37f0ff3806..7bf39a29b3 100644 --- a/core/src/io/anuke/mindustry/game/DefaultWaves.java +++ b/core/src/io/anuke/mindustry/game/DefaultWaves.java @@ -5,9 +5,9 @@ import io.anuke.mindustry.content.*; import io.anuke.mindustry.type.ItemStack; public class DefaultWaves{ - private static Array spawns; + private Array spawns; - public static Array get(){ + public Array get(){ if(spawns == null && UnitTypes.dagger != null){ spawns = Array.with( new SpawnGroup(UnitTypes.dagger){{ diff --git a/core/src/io/anuke/mindustry/game/Difficulty.java b/core/src/io/anuke/mindustry/game/Difficulty.java index 8dc4a79269..3b65017ff3 100644 --- a/core/src/io/anuke/mindustry/game/Difficulty.java +++ b/core/src/io/anuke/mindustry/game/Difficulty.java @@ -2,10 +2,7 @@ package io.anuke.mindustry.game; import io.anuke.arc.Core; -/** - * Presets for time between waves. - * TODO specify correct time - */ +/** Presets for time between waves. Currently unused.*/ public enum Difficulty{ easy(1.4f), normal(1f), diff --git a/core/src/io/anuke/mindustry/game/EventType.java b/core/src/io/anuke/mindustry/game/EventType.java index 872f74a1c1..8bc340ce2e 100644 --- a/core/src/io/anuke/mindustry/game/EventType.java +++ b/core/src/io/anuke/mindustry/game/EventType.java @@ -32,6 +32,10 @@ public class EventType{ } + public static class DisposeEvent{ + + } + public static class PlayEvent{ } @@ -129,6 +133,8 @@ public class EventType{ } } + /** Called right before a block is destroyed. + * The tile entity of the tile in this event cannot be null when this happens.*/ public static class BlockDestroyEvent{ public final Tile tile; diff --git a/core/src/io/anuke/mindustry/game/Gamemode.java b/core/src/io/anuke/mindustry/game/Gamemode.java index 6118b273ef..ed492b6afb 100644 --- a/core/src/io/anuke/mindustry/game/Gamemode.java +++ b/core/src/io/anuke/mindustry/game/Gamemode.java @@ -1,15 +1,18 @@ package io.anuke.mindustry.game; -import io.anuke.arc.Core; -import io.anuke.arc.function.Consumer; +import io.anuke.arc.*; +import io.anuke.arc.function.*; +import io.anuke.mindustry.maps.*; -/** Defines preset rule sets.. */ +import static io.anuke.mindustry.Vars.waveTeam; + +/** Defines preset rule sets. */ public enum Gamemode{ survival(rules -> { rules.waveTimer = true; rules.waves = true; rules.unitDrops = true; - }), + }, map -> map.spawns > 0), sandbox(rules -> { rules.infiniteResources = true; rules.waves = true; @@ -21,7 +24,7 @@ public enum Gamemode{ rules.unitDrops = true; rules.waves = false; rules.attackMode = true; - }), + }, map -> map.teams.contains(waveTeam.ordinal())), pvp(rules -> { rules.pvp = true; rules.enemyCoreBuildRadius = 600f; @@ -33,7 +36,7 @@ public enum Gamemode{ rules.unitBuildSpeedMultiplier = 3f; rules.unitHealthMultiplier = 3f; rules.attackMode = true; - }), + }, map -> map.teams.size > 1), editor(true, rules -> { rules.infiniteResources = true; rules.editor = true; @@ -44,15 +47,27 @@ public enum Gamemode{ }); private final Consumer rules; + private final Predicate validator; + public final boolean hidden; + public final static Gamemode[] all = values(); Gamemode(Consumer rules){ this(false, rules); } Gamemode(boolean hidden, Consumer rules){ + this(hidden, rules, m -> true); + } + + Gamemode(Consumer rules, Predicate validator){ + this(false, rules, validator); + } + + Gamemode(boolean hidden, Consumer rules, Predicate validator){ this.rules = rules; this.hidden = hidden; + this.validator = validator; } /** Applies this preset to this ruleset. */ @@ -61,6 +76,11 @@ public enum Gamemode{ return in; } + /** @return whether this mode can be played on the specified map. */ + public boolean valid(Map map){ + return validator.test(map); + } + public String description(){ return Core.bundle.get("mode." + name() + ".description"); } diff --git a/core/src/io/anuke/mindustry/game/Rules.java b/core/src/io/anuke/mindustry/game/Rules.java index 594dec123c..a3ee87615b 100644 --- a/core/src/io/anuke/mindustry/game/Rules.java +++ b/core/src/io/anuke/mindustry/game/Rules.java @@ -2,7 +2,9 @@ package io.anuke.mindustry.game; import io.anuke.annotations.Annotations.Serialize; import io.anuke.arc.collection.Array; +import io.anuke.mindustry.content.Items; import io.anuke.mindustry.io.JsonIO; +import io.anuke.mindustry.type.ItemStack; import io.anuke.mindustry.type.Zone; /** @@ -22,7 +24,7 @@ public class Rules{ /** Whether the game objective is PvP. Note that this enables automatic hosting. */ public boolean pvp; /** Whether enemy units drop random items on death. */ - public boolean unitDrops; + public boolean unitDrops = true; /** How fast unit pads build units. */ public float unitBuildSpeedMultiplier = 1f; /** How much health units start with. */ @@ -40,7 +42,7 @@ public class Rules{ /** No-build zone around enemy core radius. */ public float enemyCoreBuildRadius = 400f; /** Radius around enemy wave drop zones.*/ - public float dropZoneRadius = 380f; + public float dropZoneRadius = 300f; /** Player respawn time in ticks. */ public float respawnTime = 60 * 4; /** Time between waves in ticks. */ @@ -51,8 +53,8 @@ public class Rules{ public float launchWaveMultiplier = 2f; /** Zone for saves that have them.*/ public Zone zone; - /** Spawn layout. Should be assigned on save load based on map or zone. */ - public Array spawns = DefaultWaves.get(); + /** Spawn layout. */ + public Array spawns = new Array<>(); /** Determines if there should be limited respawns. */ public boolean limitedRespawns = false; /** How many times player can respawn during one wave. */ @@ -63,6 +65,8 @@ public class Rules{ public boolean attackMode = false; /** Whether this is the editor gamemode. */ public boolean editor = false; + /** Starting items put in cores */ + public Array loadout = Array.with(ItemStack.with(Items.copper, 200)); /** Copies this ruleset exactly. Not very efficient at all, do not use often. */ public Rules copy(){ diff --git a/core/src/io/anuke/mindustry/game/Teams.java b/core/src/io/anuke/mindustry/game/Teams.java index bf328255ca..be4d1a7e2c 100644 --- a/core/src/io/anuke/mindustry/game/Teams.java +++ b/core/src/io/anuke/mindustry/game/Teams.java @@ -1,5 +1,6 @@ package io.anuke.mindustry.game; +import io.anuke.annotations.Annotations.Struct; import io.anuke.arc.collection.*; import io.anuke.mindustry.Vars; import io.anuke.mindustry.world.Tile; @@ -41,14 +42,28 @@ public class Teams{ return enemiesOf(team).contains(other); } - public class TeamData{ + /** Allocates a new array with the active teams. + * Never call in the main game loop.*/ + public Array getActive(){ + return Array.select(map, t -> t != null); + } + + public static class TeamData{ public final ObjectSet cores = new ObjectSet<>(); public final EnumSet enemies; public final Team team; + public LongQueue brokenBlocks = new LongQueue(); public TeamData(Team team, EnumSet enemies){ this.team = team; this.enemies = enemies; } } + + /** Represents a block made by this team that was destroyed somewhere on the map. + * This does not include deconstructed blocks.*/ + @Struct + public class BrokenBlockStruct{ + public short x, y, rotation, block; + } } diff --git a/core/src/io/anuke/mindustry/game/TypeID.java b/core/src/io/anuke/mindustry/game/TypeID.java new file mode 100644 index 0000000000..c054f9d8e9 --- /dev/null +++ b/core/src/io/anuke/mindustry/game/TypeID.java @@ -0,0 +1,19 @@ +package io.anuke.mindustry.game; + +import io.anuke.arc.function.Supplier; +import io.anuke.mindustry.entities.traits.TypeTrait; +import io.anuke.mindustry.type.ContentType; + +public class TypeID extends MappableContent{ + public final Supplier constructor; + + public TypeID(String name, Supplier constructor){ + super(name); + this.constructor = constructor; + } + + @Override + public ContentType getContentType(){ + return ContentType.typeid; + } +} diff --git a/core/src/io/anuke/mindustry/graphics/BlockRenderer.java b/core/src/io/anuke/mindustry/graphics/BlockRenderer.java index 50d904682d..292052479c 100644 --- a/core/src/io/anuke/mindustry/graphics/BlockRenderer.java +++ b/core/src/io/anuke/mindustry/graphics/BlockRenderer.java @@ -1,22 +1,16 @@ package io.anuke.mindustry.graphics; -import io.anuke.arc.Core; -import io.anuke.arc.Events; -import io.anuke.arc.collection.Array; -import io.anuke.arc.collection.Sort; +import io.anuke.arc.*; +import io.anuke.arc.collection.*; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.Texture.TextureFilter; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.graphics.g2d.Fill; +import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.graphics.glutils.FrameBuffer; -import io.anuke.arc.util.Disposable; -import io.anuke.arc.util.Tmp; +import io.anuke.arc.util.*; import io.anuke.mindustry.content.Blocks; -import io.anuke.mindustry.game.EventType.TileChangeEvent; -import io.anuke.mindustry.game.EventType.WorldLoadEvent; +import io.anuke.mindustry.game.EventType.*; import io.anuke.mindustry.game.Team; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.*; import static io.anuke.arc.Core.camera; import static io.anuke.mindustry.Vars.*; diff --git a/core/src/io/anuke/mindustry/graphics/Bloom.java b/core/src/io/anuke/mindustry/graphics/Bloom.java new file mode 100644 index 0000000000..734992d8c0 --- /dev/null +++ b/core/src/io/anuke/mindustry/graphics/Bloom.java @@ -0,0 +1,417 @@ +package io.anuke.mindustry.graphics; + +import io.anuke.arc.Core; +import io.anuke.arc.graphics.*; +import io.anuke.arc.graphics.Pixmap.Format; +import io.anuke.arc.graphics.VertexAttributes.Usage; +import io.anuke.arc.graphics.glutils.FrameBuffer; +import io.anuke.arc.graphics.glutils.Shader; + +/** + * Bloomlib allow easy but efficient way to add bloom effect as post process + * effect + * + * @author kalle_h + */ +public class Bloom{ + + /** + * To use implement bloom more like a glow. Texture alpha channel can be + * used as mask which part are glowing and which are not. see more info at: + * http://www.gamasutra.com/view/feature/2107/realtime_glow.php + *

+ * NOTE: need to be set before bloom instance is created. After that this + * does nothing. + */ + public static boolean useAlphaChannelAsMask = false; + + /** how many blur pass */ + public int blurPasses = 1; + + private Shader tresholdShader; + private Shader bloomShader; + + private Mesh fullScreenQuad; + + private Texture pingPongTex1; + private Texture pingPongTex2; + private Texture original; + + private FrameBuffer frameBuffer; + private FrameBuffer pingPongBuffer1; + private FrameBuffer pingPongBuffer2; + + private Shader blurShader; + + private float bloomIntensity; + private float originalIntensity; + private float threshold; + private int w; + private int h; + private boolean blending = false; + private boolean capturing = false; + private float r = 0f; + private float g = 0f; + private float b = 0f; + private float a = 1f; + private boolean disposeFBO = true; + + /** + * IMPORTANT NOTE CALL THIS WHEN RESUMING + */ + public void resume(){ + bloomShader.begin(); + { + bloomShader.setUniformi("u_texture0", 0); + bloomShader.setUniformi("u_texture1", 1); + } + bloomShader.end(); + + setSize(w, h); + setThreshold(threshold); + setBloomIntesity(bloomIntensity); + setOriginalIntesity(originalIntensity); + + original = frameBuffer.getTexture(); + pingPongTex1 = pingPongBuffer1.getTexture(); + pingPongTex2 = pingPongBuffer2.getTexture(); + } + + /** + * Initialize bloom class that capsulate original scene capturate, + * tresholding, gaussian blurring and blending. Default values: depth = true + * blending = false 32bits = true + */ + public Bloom(){ + initialize(Core.graphics.getWidth() / 4, Core.graphics.getHeight() / 4, + null, false, false, true); + } + + public Bloom(boolean useBlending){ + initialize(Core.graphics.getWidth() / 4, Core.graphics.getHeight() / 4, + null, false, useBlending, true); + } + + /** + * Initialize bloom class that capsulate original scene capturate, + * tresholding, gaussian blurring and blending. + * + * @param FBO_W + * @param FBO_H how big fbo is used for bloom texture, smaller = more blur and + * lot faster but aliasing can be problem + * @param hasDepth do rendering need depth buffer + * @param useBlending does fbo need alpha channel and is blending enabled when final + * image is rendered. This allow to combine background graphics + * and only do blooming on certain objects param use32bitFBO does + * fbo use higher precision than 16bits. + */ + public Bloom(int FBO_W, int FBO_H, boolean hasDepth, boolean useBlending, + boolean use32bitFBO){ + initialize(FBO_W, FBO_H, null, hasDepth, useBlending, use32bitFBO); + + } + + /** + * EXPERT FUNCTIONALITY. no error checking. Use this only if you know what + * you are doing. Remember that bloom.capture() clear the screen so use + * continue instead if that is a problem. + *

+ * Initialize bloom class that capsulate original scene capturate, + * tresholding, gaussian blurring and blending. + *

+ * * @param sceneIsCapturedHere diposing is user responsibility. + * + * @param FBO_W + * @param FBO_H how big fbo is used for bloom texture, smaller = more blur and + * lot faster but aliasing can be problem + * @param useBlending does fbo need alpha channel and is blending enabled when final + * image is rendered. This allow to combine background graphics + * and only do blooming on certain objects param use32bitFBO does + * fbo use higher precision than 16bits. + */ + public Bloom(int FBO_W, int FBO_H, FrameBuffer sceneIsCapturedHere, + boolean useBlending, boolean use32bitFBO){ + + initialize(FBO_W, FBO_H, sceneIsCapturedHere, false, useBlending, + use32bitFBO); + disposeFBO = false; + } + + private void initialize(int FBO_W, int FBO_H, FrameBuffer fbo, + boolean hasDepth, boolean useBlending, boolean use32bitFBO){ + blending = useBlending; + Format format = null; + + if(use32bitFBO){ + if(useBlending){ + format = Format.RGBA8888; + }else{ + format = Format.RGB888; + } + + }else{ + if(useBlending){ + format = Format.RGBA4444; + }else{ + format = Format.RGB565; + } + } + if(fbo == null){ + frameBuffer = new FrameBuffer(format, Core.graphics.getWidth(), + Core.graphics.getHeight(), hasDepth); + }else{ + frameBuffer = fbo; + } + + pingPongBuffer1 = new FrameBuffer(format, FBO_W, FBO_H, false); + + pingPongBuffer2 = new FrameBuffer(format, FBO_W, FBO_H, false); + + original = frameBuffer.getTexture(); + pingPongTex1 = pingPongBuffer1.getTexture(); + pingPongTex2 = pingPongBuffer2.getTexture(); + + fullScreenQuad = createFullScreenQuad(); + final String alpha = useBlending ? "alpha_" : ""; + + bloomShader = createShader("screenspace", alpha + "bloom"); + + if(useAlphaChannelAsMask){ + tresholdShader = createShader("screenspace", "maskedtreshold"); + }else{ + tresholdShader = createShader("screenspace", alpha + "threshold"); + } + + blurShader = createShader("blurspace", alpha + "gaussian"); + + setSize(FBO_W, FBO_H); + setBloomIntesity(2.5f); + setOriginalIntesity(0.8f); + setThreshold(0.5f); + + bloomShader.begin(); + { + bloomShader.setUniformi("u_texture0", 0); + bloomShader.setUniformi("u_texture1", 1); + } + bloomShader.end(); + } + + /** + * Set clearing color for capturing buffer + * + * @param r + * @param g + * @param b + * @param a + */ + public void setClearColor(float r, float g, float b, float a){ + this.r = r; + this.g = g; + this.b = b; + this.a = a; + } + + /** + * Call this before rendering scene. + */ + public void capture(){ + if(!capturing){ + capturing = true; + frameBuffer.begin(); + Core.gl.glClearColor(r, g, b, a); + Core.gl.glClear(GL20.GL_COLOR_BUFFER_BIT); + + } + } + + /** + * Pause capturing to fbo. + */ + public void capturePause(){ + if(capturing){ + capturing = false; + frameBuffer.end(); + } + } + + /** Start capturing again after pause, no clearing is done to framebuffer */ + public void captureContinue(){ + if(!capturing){ + capturing = true; + frameBuffer.begin(); + } + } + + /** + * Call this after scene. Renders the bloomed scene. + */ + public void render(){ + if(capturing){ + capturing = false; + frameBuffer.end(); + } + + Core.gl.glDisable(GL20.GL_BLEND); + Core.gl.glDisable(GL20.GL_DEPTH_TEST); + Core.gl.glDepthMask(false); + + gaussianBlur(); + + if(blending){ + Core.gl.glEnable(GL20.GL_BLEND); + Core.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA); + } + + pingPongTex1.bind(1); + original.bind(0); + bloomShader.begin(); + { + fullScreenQuad.render(bloomShader, GL20.GL_TRIANGLE_FAN); + } + bloomShader.end(); + + } + + private void gaussianBlur(){ + + // cut bright areas of the picture and blit to smaller fbo + + original.bind(0); + pingPongBuffer1.begin(); + { + tresholdShader.begin(); + { + // tresholdShader.setUniformi("u_texture0", 0); + fullScreenQuad.render(tresholdShader, GL20.GL_TRIANGLE_FAN, 0, + 4); + } + tresholdShader.end(); + } + pingPongBuffer1.end(); + + for(int i = 0; i < blurPasses; i++){ + + pingPongTex1.bind(0); + + // horizontal + pingPongBuffer2.begin(); + { + blurShader.begin(); + { + blurShader.setUniformf("dir", 1f, 0f); + fullScreenQuad.render(blurShader, GL20.GL_TRIANGLE_FAN, 0, + 4); + } + blurShader.end(); + } + pingPongBuffer2.end(); + + pingPongTex2.bind(0); + // vertical + pingPongBuffer1.begin(); + { + blurShader.begin(); + { + blurShader.setUniformf("dir", 0f, 1f); + + fullScreenQuad.render(blurShader, GL20.GL_TRIANGLE_FAN, 0, + 4); + } + blurShader.end(); + } + pingPongBuffer1.end(); + } + } + + /** + * set intensity for bloom. higher mean more brightening for spots that are + * over threshold + * + * @param intensity multiplier for blurred texture in combining phase. must be + * positive. + */ + public void setBloomIntesity(float intensity){ + bloomIntensity = intensity; + bloomShader.begin(); + { + bloomShader.setUniformf("BloomIntensity", intensity); + } + bloomShader.end(); + } + + /** + * set intensity for original scene. under 1 mean darkening and over 1 means + * lightening + * + * @param intensity multiplier for captured texture in combining phase. must be + * positive. + */ + public void setOriginalIntesity(float intensity){ + originalIntensity = intensity; + bloomShader.begin(); + { + bloomShader.setUniformf("OriginalIntensity", intensity); + } + bloomShader.end(); + } + + /** + * Treshold for bright parts. everything under threshold is clamped to 0 + * + * @param threshold must be in range 0..1 + */ + public void setThreshold(float threshold){ + this.threshold = threshold; + tresholdShader.begin(); + { + tresholdShader.setUniformf("threshold", threshold, + 1f / (1 - threshold)); + } + tresholdShader.end(); + } + + private void setSize(int FBO_W, int FBO_H){ + w = FBO_W; + h = FBO_H; + blurShader.begin(); + blurShader.setUniformf("size", FBO_W, FBO_H); + blurShader.end(); + } + + /** + * Call this when application is exiting. + */ + public void dispose(){ + if(disposeFBO) + frameBuffer.dispose(); + + fullScreenQuad.dispose(); + + pingPongBuffer1.dispose(); + pingPongBuffer2.dispose(); + + blurShader.dispose(); + bloomShader.dispose(); + tresholdShader.dispose(); + + } + + private static Mesh createFullScreenQuad(){ + float[] verts = {-1, -1, 0, 0, 1, -1, 1, 0, 1, 1, 1, 1, -1, 1, 0, 1}; + Mesh tmpMesh = new Mesh(true, 4, 0, new VertexAttribute( + Usage.Position, 2, "a_position"), new VertexAttribute( + Usage.TextureCoordinates, 2, "a_texCoord0")); + + tmpMesh.setVertices(verts); + return tmpMesh; + + } + + private static Shader createShader(String vertexName, String fragmentName){ + String vertexShader = Core.files.internal("bloomshaders/" + vertexName + ".vertex.glsl").readString(); + String fragmentShader = Core.files.internal("bloomshaders/" + fragmentName + ".fragment.glsl").readString(); + return new Shader(vertexShader, fragmentShader); + } + +} diff --git a/core/src/io/anuke/mindustry/graphics/Layer.java b/core/src/io/anuke/mindustry/graphics/Layer.java index f84f6aa3c2..206da3d6e0 100644 --- a/core/src/io/anuke/mindustry/graphics/Layer.java +++ b/core/src/io/anuke/mindustry/graphics/Layer.java @@ -10,7 +10,5 @@ public enum Layer{ /** "High" blocks, like turrets. */ turret, /** Power lasers. */ - power, - /** Extra lasers, like healing turrets. */ - laser + power } diff --git a/core/src/io/anuke/mindustry/graphics/MenuRenderer.java b/core/src/io/anuke/mindustry/graphics/MenuRenderer.java new file mode 100644 index 0000000000..fb5831c903 --- /dev/null +++ b/core/src/io/anuke/mindustry/graphics/MenuRenderer.java @@ -0,0 +1,300 @@ +package io.anuke.mindustry.graphics; + +import io.anuke.arc.Core; +import io.anuke.arc.collection.Array; +import io.anuke.arc.function.PositionConsumer; +import io.anuke.arc.graphics.Camera; +import io.anuke.arc.graphics.Color; +import io.anuke.arc.graphics.g2d.*; +import io.anuke.arc.graphics.glutils.FrameBuffer; +import io.anuke.arc.math.*; +import io.anuke.arc.scene.ui.layout.Unit; +import io.anuke.arc.util.*; +import io.anuke.arc.util.noise.RidgedPerlin; +import io.anuke.arc.util.noise.Simplex; +import io.anuke.mindustry.content.Blocks; +import io.anuke.mindustry.content.UnitTypes; +import io.anuke.mindustry.type.UnitType; +import io.anuke.mindustry.world.*; +import io.anuke.mindustry.world.blocks.Floor; +import io.anuke.mindustry.world.blocks.OreBlock; + +import static io.anuke.mindustry.Vars.*; + +public class MenuRenderer implements Disposable{ + private static final float darkness = 0.3f; + private final int width = !mobile ? 100 : 60, height = !mobile ? 50 : 40; + + private int cacheFloor, cacheWall; + private Camera camera = new Camera(); + private Matrix3 mat = new Matrix3(); + private FrameBuffer shadows; + private CacheBatch batch; + private float time = 0f; + private float flyerRot = 45f; + private int flyers = Mathf.chance(0.2) ? Mathf.random(35) : Mathf.random(15); + private UnitType flyerType = Structs.select(UnitTypes.wraith, UnitTypes.wraith, UnitTypes.ghoul, UnitTypes.phantom, UnitTypes.phantom, UnitTypes.revenant); + + public MenuRenderer(){ + Time.mark(); + generate(); + cache(); + Log.info("Time to generate menu: {0}", Time.elapsed()); + } + + private void generate(){ + Tile[][] tiles = world.createTiles(width, height); + Array ores = content.blocks().select(b -> b instanceof OreBlock); + shadows = new FrameBuffer(width, height); + int offset = Mathf.random(100000); + Simplex s1 = new Simplex(offset); + Simplex s2 = new Simplex(offset + 1); + Simplex s3 = new Simplex(offset + 2); + RidgedPerlin rid = new RidgedPerlin(1 + offset, 1); + Block[] selected = Structs.select( + new Block[]{Blocks.sand, Blocks.sandRocks}, + new Block[]{Blocks.shale, Blocks.shaleRocks}, + new Block[]{Blocks.ice, Blocks.icerocks}, + new Block[]{Blocks.sand, Blocks.sandRocks}, + new Block[]{Blocks.shale, Blocks.shaleRocks}, + new Block[]{Blocks.ice, Blocks.icerocks}, + new Block[]{Blocks.moss, Blocks.sporePine} + ); + Block[] selected2 = Structs.select( + new Block[]{Blocks.ignarock, Blocks.duneRocks}, + new Block[]{Blocks.ignarock, Blocks.duneRocks}, + new Block[]{Blocks.stone, Blocks.rocks}, + new Block[]{Blocks.stone, Blocks.rocks}, + new Block[]{Blocks.moss, Blocks.sporerocks}, + new Block[]{Blocks.salt, Blocks.saltRocks} + ); + + Block ore1 = ores.random(); + ores.remove(ore1); + Block ore2 = ores.random(); + + double tr1 = Mathf.random(0.65f, 0.85f); + double tr2 = Mathf.random(0.65f, 0.85f); + boolean doheat = Mathf.chance(0.25); + boolean tendrils = Mathf.chance(0.25); + boolean tech = Mathf.chance(0.25); + int secSize = 10; + + Block floord = selected[0], walld = selected[1]; + Block floord2 = selected2[0], walld2 = selected2[1]; + + for(int x = 0; x < width; x++){ + for(int y = 0; y < height; y++){ + Block floor = floord; + Block ore = Blocks.air; + Block wall = Blocks.air; + + if(s1.octaveNoise2D(3, 0.5, 1/20.0, x, y) > 0.5){ + wall = walld; + } + + if(s3.octaveNoise2D(3, 0.5, 1/20.0, x, y) > 0.5){ + floor = floord2; + if(wall != Blocks.air){ + wall = walld2; + } + } + + if(s2.octaveNoise2D(3, 0.3, 1/30.0, x, y) > tr1){ + ore = ore1; + } + + if(s2.octaveNoise2D(2, 0.2, 1/15.0, x, y+99999) > tr2){ + ore = ore2; + } + + if(doheat){ + double heat = s3.octaveNoise2D(4, 0.6, 1 / 50.0, x, y + 9999); + double base = 0.65; + + if(heat > base){ + ore = Blocks.air; + wall = Blocks.air; + floor = Blocks.ignarock; + + if(heat > base + 0.1){ + floor = Blocks.hotrock; + + if(heat > base + 0.15){ + floor = Blocks.magmarock; + } + } + } + } + + if(tech){ + int mx = x % secSize, my = y % secSize; + int sclx = x / secSize, scly = y / secSize; + if(s1.octaveNoise2D(2, 1f / 10f, 0.5f, sclx, scly) > 0.4f && (mx == 0 || my == 0 || mx == secSize - 1 || my == secSize - 1)){ + floor = Blocks.darkPanel3; + if(Mathf.dst(mx, my, secSize/2, secSize/2) > secSize/2f + 1){ + floor = Blocks.darkPanel4; + } + + + if(wall != Blocks.air && Mathf.chance(0.7)){ + wall = Blocks.darkMetal; + } + } + } + + if(tendrils){ + if(rid.getValue(x, y, 1f / 17f) > 0f){ + floor = Mathf.chance(0.2) ? Blocks.sporeMoss : Blocks.moss; + + if(wall != Blocks.air){ + wall = Blocks.sporerocks; + } + } + } + + Tile tile; + tiles[x][y] = (tile = new CachedTile()); + tile.x = (short)x; + tile.y = (short)y; + tile.setFloor((Floor) floor); + tile.setBlock(wall); + tile.setOverlay(ore); + } + } + } + + private void cache(){ + + //draw shadows + Draw.proj().setOrtho(0, 0, shadows.getWidth(), shadows.getHeight()); + shadows.beginDraw(Color.CLEAR); + Draw.color(Color.BLACK); + for(int x = 0; x < width; x++){ + for(int y = 0; y < height; y++){ + if(world.rawTile(x, y).block() != Blocks.air){ + Fill.rect(x + 0.5f, y + 0.5f, 1, 1); + } + } + } + Draw.color(); + shadows.endDraw(); + + SpriteBatch prev = Core.batch; + + Core.batch = batch = new CacheBatch(new SpriteCache(width * height * 6, false)); + batch.beginCache(); + + for(int x = 0; x < width; x++){ + for(int y = 0; y < height; y++){ + Tile tile = world.rawTile(x, y); + tile.floor().draw(tile); + } + } + + for(int x = 0; x < width; x++){ + for(int y = 0; y < height; y++){ + Tile tile = world.rawTile(x, y); + if(tile.overlay() != Blocks.air){ + tile.overlay().draw(tile); + } + } + } + + cacheFloor = batch.endCache(); + batch.beginCache(); + + for(int x = 0; x < width; x++){ + for(int y = 0; y < height; y++){ + Tile tile = world.rawTile(x, y); + if(tile.block() != Blocks.air){ + tile.block().draw(tile); + } + } + } + + cacheWall = batch.endCache(); + + Core.batch = prev; + } + + public void render(){ + time += Time.delta(); + float scaling = Math.max(Unit.dp.scl(4f), Math.max(Core.graphics.getWidth() / ((width - 1f) * tilesize), Core.graphics.getHeight() / ((height - 1f) * tilesize))); + camera.position.set(width * tilesize / 2f, height * tilesize / 2f); + camera.resize(Core.graphics.getWidth() / scaling, + Core.graphics.getHeight() / scaling); + + mat.set(Draw.proj()); + Draw.flush(); + Draw.proj(camera.projection()); + batch.setProjection(camera.projection()); + batch.beginDraw(); + batch.drawCache(cacheFloor); + batch.endDraw(); + Draw.rect(Draw.wrap(shadows.getTexture()), + width * tilesize / 2f - 4f, height * tilesize / 2f - 4f, + width * tilesize, -height * tilesize); + Draw.flush(); + batch.beginDraw(); + batch.drawCache(cacheWall); + batch.endDraw(); + + drawFlyers(); + + Draw.proj(mat); + Draw.color(0f, 0f, 0f, darkness); + Fill.crect(0, 0, Core.graphics.getWidth(), Core.graphics.getHeight()); + Draw.color(); + } + + private void drawFlyers(){ + Draw.color(0f, 0f, 0f, 0.4f); + + float size = Math.max(flyerType.iconRegion.getWidth(), flyerType.iconRegion.getHeight()) * Draw.scl * 1.6f; + + flyers((x, y) -> { + Draw.rect(flyerType.region, x - 12f, y - 13f, flyerRot - 90); + }); + + flyers((x, y) -> { + Draw.rect("circle-shadow", x, y, size, size); + }); + Draw.color(); + + flyers((x, y) -> { + float engineOffset = flyerType.engineOffset, engineSize = flyerType.engineSize, rotation = flyerRot; + + Draw.color(Pal.engine); + Fill.circle(x + Angles.trnsx(rotation + 180, engineOffset), y + Angles.trnsy(rotation + 180, engineOffset), + engineSize + Mathf.absin(Time.time(), 2f, engineSize / 4f)); + + Draw.color(Color.WHITE); + Fill.circle(x + Angles.trnsx(rotation + 180, engineOffset - 1f), y + Angles.trnsy(rotation + 180, engineOffset - 1f), + (engineSize + Mathf.absin(Time.time(), 2f, engineSize / 4f)) / 2f); + Draw.color(); + + Draw.rect(flyerType.region, x, y, flyerRot - 90); + }); + } + + private void flyers(PositionConsumer cons){ + float tw = width * tilesize * 1f + tilesize; + float th = height * tilesize * 1f + tilesize; + float range = 500f; + float offset = -100f; + + for(int i = 0; i < flyers; i++){ + Tmp.v1.trns(flyerRot, time * (2f + flyerType.speed)); + + cons.accept((Mathf.randomSeedRange(i, range) + Tmp.v1.x + Mathf.absin(time + Mathf.randomSeedRange(i + 2, 500), 10f, 3.4f) + offset) % (tw + Mathf.randomSeed(i + 5, 0, 500)), + (Mathf.randomSeedRange(i + 1, range) + Tmp.v1.y + Mathf.absin(time + Mathf.randomSeedRange(i + 3, 500), 10f, 3.4f) + offset) % th); + } + } + + @Override + public void dispose(){ + batch.dispose(); + shadows.dispose(); + } +} diff --git a/core/src/io/anuke/mindustry/graphics/MinimapRenderer.java b/core/src/io/anuke/mindustry/graphics/MinimapRenderer.java index 9777f4e833..85b390d939 100644 --- a/core/src/io/anuke/mindustry/graphics/MinimapRenderer.java +++ b/core/src/io/anuke/mindustry/graphics/MinimapRenderer.java @@ -1,23 +1,20 @@ package io.anuke.mindustry.graphics; -import io.anuke.arc.Core; -import io.anuke.arc.Events; -import io.anuke.arc.collection.Array; +import io.anuke.arc.*; +import io.anuke.arc.collection.*; import io.anuke.arc.graphics.*; -import io.anuke.arc.graphics.Pixmap.Format; +import io.anuke.arc.graphics.Pixmap.*; import io.anuke.arc.graphics.g2d.*; -import io.anuke.arc.math.Mathf; -import io.anuke.arc.math.geom.Rectangle; -import io.anuke.arc.util.Disposable; -import io.anuke.mindustry.entities.Units; -import io.anuke.mindustry.entities.type.Unit; -import io.anuke.mindustry.game.EventType.TileChangeEvent; -import io.anuke.mindustry.game.EventType.WorldLoadEvent; -import io.anuke.mindustry.io.MapIO; -import io.anuke.mindustry.world.Tile; +import io.anuke.arc.math.*; +import io.anuke.arc.math.geom.*; +import io.anuke.arc.util.*; +import io.anuke.mindustry.entities.*; +import io.anuke.mindustry.entities.type.*; +import io.anuke.mindustry.game.EventType.*; +import io.anuke.mindustry.io.*; +import io.anuke.mindustry.world.*; -import static io.anuke.mindustry.Vars.tilesize; -import static io.anuke.mindustry.Vars.world; +import static io.anuke.mindustry.Vars.*; public class MinimapRenderer implements Disposable{ private static final float baseSize = 16f; @@ -129,8 +126,9 @@ public class MinimapRenderer implements Disposable{ } private int colorFor(Tile tile){ + if(tile == null) return 0; tile = tile.link(); - return MapIO.colorFor(tile.floor(), tile.block(), tile.overlay(), tile.getTeam()); + return Tmp.c1.set(MapIO.colorFor(tile.floor(), tile.block(), tile.overlay(), tile.getTeam())).mul(tile.block().cacheLayer == CacheLayer.walls ? 1f - tile.rotation() / 4f : 1f).rgba(); } @Override diff --git a/core/src/io/anuke/mindustry/graphics/OverlayRenderer.java b/core/src/io/anuke/mindustry/graphics/OverlayRenderer.java index 494099befb..bccb17ebb7 100644 --- a/core/src/io/anuke/mindustry/graphics/OverlayRenderer.java +++ b/core/src/io/anuke/mindustry/graphics/OverlayRenderer.java @@ -22,6 +22,7 @@ import static io.anuke.mindustry.Vars.*; public class OverlayRenderer{ private static final float indicatorLength = 14f; + private static final float spawnerMargin = tilesize*11f; private static final Rectangle rect = new Rectangle(); private float buildFadeTime; @@ -92,6 +93,16 @@ public class OverlayRenderer{ } } + Lines.stroke(2f); + Draw.color(Color.GRAY, Color.LIGHT_GRAY, Mathf.absin(Time.time(), 8f, 1f)); + + for(Tile tile : world.spawner.getGroundSpawns()){ + if(tile.withinDst(player.x, player.y, state.rules.dropZoneRadius + spawnerMargin)){ + Draw.alpha(Mathf.clamp(1f - (player.dst(tile) - state.rules.dropZoneRadius) / spawnerMargin)); + Lines.dashCircle(tile.worldx(), tile.worldy(), state.rules.dropZoneRadius); + } + } + Draw.reset(); //draw selected block bars and info diff --git a/core/src/io/anuke/mindustry/graphics/Pal.java b/core/src/io/anuke/mindustry/graphics/Pal.java index aa4ca6f7e7..40c4867abc 100644 --- a/core/src/io/anuke/mindustry/graphics/Pal.java +++ b/core/src/io/anuke/mindustry/graphics/Pal.java @@ -11,6 +11,8 @@ public class Pal{ bulletYellow = Color.valueOf("ffeec9"), bulletYellowBack = Color.valueOf("f9c87a"), + darkMetal = Color.valueOf("6e7080"), + missileYellow = Color.valueOf("ffd2ae"), missileYellowBack = Color.valueOf("e58956"), @@ -50,10 +52,11 @@ public class Pal{ bar = Color.SLATE, accent = Color.valueOf("ffd37f"), stat = Color.valueOf("ffd37f"), - locked = Color.valueOf("989aa4"), + gray = Color.valueOf("454545"), accentBack = Color.valueOf("d4816b"), place = Color.valueOf("6335f8"), remove = Color.valueOf("e55454"), + noplace = Color.valueOf("ffa697"), removeBack = Color.valueOf("a73e3e"), placeRotate = accent, breakInvalid = Color.valueOf("d44b3d"), diff --git a/core/src/io/anuke/mindustry/graphics/Pixelator.java b/core/src/io/anuke/mindustry/graphics/Pixelator.java index e8a9e0d2f3..8cc252eebd 100644 --- a/core/src/io/anuke/mindustry/graphics/Pixelator.java +++ b/core/src/io/anuke/mindustry/graphics/Pixelator.java @@ -55,7 +55,7 @@ public class Pixelator implements Disposable{ Draw.rect(Draw.wrap(buffer.getTexture()), Core.camera.position.x, Core.camera.position.y, Core.camera.width, -Core.camera.height); Draw.blend(); - renderer.drawAndInterpolate(playerGroup, p -> !p.isDead() && !p.isLocal, Player::drawName); + renderer.draw(playerGroup, p -> !p.isDead() && !p.isLocal, Player::drawName); Core.camera.position.set(px, py); Core.settings.put("animatedwater", hadWater); diff --git a/core/src/io/anuke/mindustry/graphics/Shapes.java b/core/src/io/anuke/mindustry/graphics/Shapes.java index 7e629d347b..3ab13f8c74 100644 --- a/core/src/io/anuke/mindustry/graphics/Shapes.java +++ b/core/src/io/anuke/mindustry/graphics/Shapes.java @@ -7,24 +7,22 @@ import io.anuke.arc.util.Tmp; public class Shapes{ - public static void laser(String line, String edge, float x, float y, float x2, float y2, float scale){ + public static void laser(TextureRegion line, TextureRegion edge, float x, float y, float x2, float y2, float scale){ laser(line, edge, x, y, x2, y2, Mathf.angle(x2 - x, y2 - y), scale); } - public static void laser(String line, String edge, float x, float y, float x2, float y2){ + public static void laser(TextureRegion line, TextureRegion edge, float x, float y, float x2, float y2){ laser(line, edge, x, y, x2, y2, Mathf.angle(x2 - x, y2 - y), 1f); } - public static void laser(String line, String edge, float x, float y, float x2, float y2, float rotation, float scale){ - TextureRegion region = Core.atlas.find(edge); - + public static void laser(TextureRegion line, TextureRegion edge, float x, float y, float x2, float y2, float rotation, float scale){ Tmp.v1.trns(rotation, 8f * scale * Draw.scl); - Draw.rect(Core.atlas.find(edge), x, y, region.getWidth() * scale * Draw.scl, region.getHeight() * scale * Draw.scl, rotation + 180); - Draw.rect(Core.atlas.find(edge), x2, y2, region.getWidth() * scale * Draw.scl, region.getHeight() * scale * Draw.scl, rotation); + Draw.rect(edge, x, y, edge.getWidth() * scale * Draw.scl, edge.getHeight() * scale * Draw.scl, rotation + 180); + Draw.rect(edge, x2, y2, edge.getWidth() * scale * Draw.scl, edge.getHeight() * scale * Draw.scl, rotation); Lines.stroke(12f * scale); - Lines.line(Core.atlas.find(line), x + Tmp.v1.x, y + Tmp.v1.y, x2 - Tmp.v1.x, y2 - Tmp.v1.y, CapStyle.none, 0f); + Lines.line(line, x + Tmp.v1.x, y + Tmp.v1.y, x2 - Tmp.v1.x, y2 - Tmp.v1.y, CapStyle.none, 0f); Lines.stroke(1f); } diff --git a/core/src/io/anuke/mindustry/input/DesktopInput.java b/core/src/io/anuke/mindustry/input/DesktopInput.java index 2198f002ef..87b8a26a32 100644 --- a/core/src/io/anuke/mindustry/input/DesktopInput.java +++ b/core/src/io/anuke/mindustry/input/DesktopInput.java @@ -141,7 +141,7 @@ public class DesktopInput extends InputHandler{ if(state.is(State.menu) || Core.scene.hasDialog()) return; - //zoom and rotate things + //zoom things if(Math.abs(Core.input.axisTap(Binding.zoom)) > 0 && (Core.input.keyDown(Binding.zoom_hold))){ renderer.scaleCamera(Core.input.axisTap(Binding.zoom)); } @@ -214,7 +214,7 @@ public class DesktopInput extends InputHandler{ mode = placing; }else if(selected != null){ //only begin shooting if there's no cursor event - if(!tileTapped(selected) && !tryTapPlayer(Core.input.mouseWorld().x, Core.input.mouseWorld().y) && player.getPlaceQueue().size == 0 && !droppingItem && + if(!tileTapped(selected) && !tryTapPlayer(Core.input.mouseWorld().x, Core.input.mouseWorld().y) && player.buildQueue().size == 0 && !droppingItem && !tryBeginMine(selected) && player.getMineTile() == null && !ui.chatfrag.chatOpen()){ player.isShooting = true; } @@ -222,7 +222,7 @@ public class DesktopInput extends InputHandler{ player.isShooting = true; } }else if(Core.input.keyTap(Binding.deselect) && (block != null || mode != none || player.isBuilding()) && - !(player.getCurrentRequest() != null && player.getCurrentRequest().breaking && Core.keybinds.get(Binding.deselect) == Core.keybinds.get(Binding.break_block))){ + !(player.buildRequest() != null && player.buildRequest().breaking && Core.keybinds.get(Binding.deselect) == Core.keybinds.get(Binding.break_block))){ if(block == null){ player.clearBuilding(); } diff --git a/core/src/io/anuke/mindustry/input/InputHandler.java b/core/src/io/anuke/mindustry/input/InputHandler.java index f69c9331a6..fae86625e8 100644 --- a/core/src/io/anuke/mindustry/input/InputHandler.java +++ b/core/src/io/anuke/mindustry/input/InputHandler.java @@ -42,7 +42,7 @@ public abstract class InputHandler implements InputProcessor{ /** Distance on the back from where items originate. */ final static float backTrns = 3f; - public final OverlayFragment frag = new OverlayFragment(this); + public final OverlayFragment frag = new OverlayFragment(); public Block block; public int rotation; @@ -324,7 +324,7 @@ public abstract class InputHandler implements InputProcessor{ } public boolean validBreak(int x, int y){ - return Build.validBreak(player.getTeam(), x, y) && Mathf.dst(player.x, player.y, x * tilesize, y * tilesize) < Player.placeDistance; + return Build.validBreak(player.getTeam(), x, y); } public void placeBlock(int x, int y, Block block, int rotation){ diff --git a/core/src/io/anuke/mindustry/input/MobileInput.java b/core/src/io/anuke/mindustry/input/MobileInput.java index a4b741e1a8..0bdbbbc7b3 100644 --- a/core/src/io/anuke/mindustry/input/MobileInput.java +++ b/core/src/io/anuke/mindustry/input/MobileInput.java @@ -20,6 +20,7 @@ import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.entities.Effects; import io.anuke.mindustry.entities.Units; +import io.anuke.mindustry.entities.traits.BuilderTrait.*; import io.anuke.mindustry.entities.traits.TargetTrait; import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.entities.type.Unit; @@ -120,6 +121,19 @@ public class MobileInput extends InputHandler implements GestureListener{ return true; } } + + for(BuildRequest req : player.buildQueue()){ + Tile other = world.tile(req.x, req.y); + + if(other == null || req.breaking) continue; + + r1.setSize(req.block.size * tilesize); + r1.setCenter(other.worldx() + req.block.offset(), other.worldy() + req.block.offset()); + + if(r2.overlaps(r1)){ + return true; + } + } return false; } @@ -261,11 +275,11 @@ public class MobileInput extends InputHandler implements GestureListener{ @Override public void buildUI(Table table){ - table.addImage("blank").color(Pal.accent).height(3f).colspan(4).growX(); + table.addImage("whiteui").color(Pal.gray).height(4f).colspan(4).growX(); table.row(); table.left().margin(0f).defaults().size(48f); - table.addImageButton("icon-break", "clear-toggle-partial", 16 * 2f, () -> { + table.addImageButton("icon-break-small", "clear-toggle-partial", iconsizesmall, () -> { mode = mode == breaking ? block == null ? none : placing : breaking; lastBlock = block; if(mode == breaking){ @@ -274,17 +288,17 @@ public class MobileInput extends InputHandler implements GestureListener{ }).update(l -> l.setChecked(mode == breaking)); //diagonal swap button - table.addImageButton("icon-diagonal", "clear-toggle-partial", 16 * 2f, () -> { + table.addImageButton("icon-diagonal-small", "clear-toggle-partial", iconsizesmall, () -> { Core.settings.put("swapdiagonal", !Core.settings.getBool("swapdiagonal")); Core.settings.save(); }).update(l -> l.setChecked(Core.settings.getBool("swapdiagonal"))); //rotate button - table.addImageButton("icon-arrow", "clear-partial", 16 * 2f, () -> rotation = Mathf.mod(rotation + 1, 4)) + table.addImageButton("icon-arrow-small", "clear-partial", iconsizesmall, () -> rotation = Mathf.mod(rotation + 1, 4)) .update(i -> i.getImage().setRotationOrigin(rotation * 90, Align.center)).visible(() -> block != null && block.rotate); //confirm button - table.addImageButton("icon-check", "clear-partial", 16 * 2f, () -> { + table.addImageButton("icon-check-small", "clear-partial", iconsizesmall, () -> { for(PlaceRequest request : selection){ Tile tile = request.tile(); @@ -475,7 +489,10 @@ public class MobileInput extends InputHandler implements GestureListener{ //call tap events if(pointer == 0 && !selecting && mode == none){ - tryTapPlayer(worldx, worldy); + if(!tryTapPlayer(worldx, worldy) && Core.settings.getBool("keyboard")){ + //shoot on touch down when in keyboard mode + player.isShooting = true; + } } return false; @@ -598,6 +615,27 @@ public class MobileInput extends InputHandler implements GestureListener{ mode = none; } + //zoom things + if(Math.abs(Core.input.axisTap(Binding.zoom)) > 0 && (Core.input.keyDown(Binding.zoom_hold))){ + renderer.scaleCamera(Core.input.axisTap(Binding.zoom)); + } + + if(!Core.settings.getBool("keyboard")){ + //move camera around + float camSpeed = 6f; + Core.camera.position.add(Tmp.v1.setZero().add(Core.input.axis(Binding.move_x), Core.input.axis(Binding.move_y)).nor().scl(Time.delta() * camSpeed)); + } + + if(Core.settings.getBool("keyboard")){ + if(Core.input.keyRelease(Binding.select)){ + player.isShooting = false; + } + + if(player.isShooting && !canShoot()){ + player.isShooting = false; + } + } + //reset state when not placing if(mode == none){ selecting = false; @@ -678,7 +716,7 @@ public class MobileInput extends InputHandler implements GestureListener{ @Override public boolean pan(float x, float y, float deltaX, float deltaY){ - if(Core.scene.hasDialog()) return false; + if(Core.scene.hasDialog() || Core.settings.getBool("keyboard")) return false; float scale = Core.camera.width / Core.graphics.getWidth(); deltaX *= scale; @@ -723,6 +761,7 @@ public class MobileInput extends InputHandler implements GestureListener{ @Override public boolean zoom(float initialDistance, float distance){ + if(Core.settings.getBool("keyboard")) return false; if(lastDistance == -1) lastDistance = initialDistance; float amount = (Mathf.sign(distance > lastDistance) * 0.04f) * Time.delta(); diff --git a/core/src/io/anuke/mindustry/io/Changelogs.java b/core/src/io/anuke/mindustry/io/Changelogs.java deleted file mode 100644 index 33d888be47..0000000000 --- a/core/src/io/anuke/mindustry/io/Changelogs.java +++ /dev/null @@ -1,54 +0,0 @@ -package io.anuke.mindustry.io; - -import io.anuke.arc.collection.Array; -import io.anuke.arc.function.Consumer; -import io.anuke.arc.util.serialization.JsonReader; -import io.anuke.arc.util.serialization.JsonValue; -import io.anuke.mindustry.net.Net; - -import static io.anuke.mindustry.Vars.releasesURL; - -public class Changelogs{ - - public static void getChangelog(Consumer> success, Consumer fail){ - Net.http(releasesURL, "GET", result -> { - JsonReader reader = new JsonReader(); - JsonValue value = reader.parse(result).child; - Array out = new Array<>(); - - while(value != null){ - String name = value.getString("name"); - String description = value.getString("body").replace("\r", ""); - int id = value.getInt("id"); - int build = Integer.parseInt(value.getString("tag_name").substring(1)); - out.add(new VersionInfo(name, description, id, build, value.getString("published_at"))); - value = value.next; - } - - success.accept(out); - }, fail); - } - - public static class VersionInfo{ - public final String name, description, date; - public final int id, build; - - public VersionInfo(String name, String description, int id, int build, String date){ - this.name = name; - this.description = description; - this.id = id; - this.build = build; - this.date = date; - } - - @Override - public String toString(){ - return "VersionInfo{" + - "name='" + name + '\'' + - ", description='" + description + '\'' + - ", id=" + id + - ", build=" + build + - '}'; - } - } -} diff --git a/core/src/io/anuke/mindustry/io/JsonIO.java b/core/src/io/anuke/mindustry/io/JsonIO.java index 3c1ce9520c..6cea5fb1c1 100644 --- a/core/src/io/anuke/mindustry/io/JsonIO.java +++ b/core/src/io/anuke/mindustry/io/JsonIO.java @@ -1,17 +1,19 @@ package io.anuke.mindustry.io; -import io.anuke.arc.util.serialization.Json; -import io.anuke.arc.util.serialization.JsonValue; -import io.anuke.mindustry.Vars; -import io.anuke.mindustry.game.Rules; -import io.anuke.mindustry.game.SpawnGroup; +import io.anuke.arc.collection.*; +import io.anuke.arc.util.serialization.*; +import io.anuke.mindustry.*; +import io.anuke.mindustry.game.*; +import io.anuke.mindustry.game.Teams.*; import io.anuke.mindustry.type.*; +import io.anuke.mindustry.world.*; @SuppressWarnings("unchecked") public class JsonIO{ private static Json json = new Json(){{ setIgnoreUnknownFields(true); setElementType(Rules.class, "spawns", SpawnGroup.class); + setElementType(Rules.class, "loadout", ItemStack.class); setSerializer(Zone.class, new Serializer(){ @Override @@ -36,6 +38,70 @@ public class JsonIO{ return Vars.content.getByName(ContentType.item, jsonData.asString()); } }); + + //TODO extremely hacky and disgusting + for(Block block : Vars.content.blocks()){ + Class type = block.getClass(); + if(type.isAnonymousClass()) type = type.getSuperclass(); + + setSerializer(type, new Serializer(){ + @Override + public void write(Json json, Block object, Class knownType){ + json.writeValue(object.name); + } + + @Override + public Block read(Json json, JsonValue jsonData, Class type){ + return Vars.content.getByName(ContentType.block, jsonData.asString()); + } + }); + } + + setSerializer(Block.class, new Serializer(){ + @Override + public void write(Json json, Block object, Class knownType){ + json.writeValue(object.name); + } + + @Override + public Block read(Json json, JsonValue jsonData, Class type){ + return Vars.content.getByName(ContentType.block, jsonData.asString()); + } + }); + + setSerializer(TeamData.class, new Serializer(){ + @Override + public void write(Json json, TeamData object, Class knownType){ + json.writeObjectStart(); + json.writeValue("brokenBlocks", object.brokenBlocks.toArray()); + json.writeValue("team", object.team.ordinal()); + json.writeObjectEnd(); + } + + @Override + public TeamData read(Json json, JsonValue jsonData, Class type){ + long[] blocks = jsonData.get("brokenBlocks").asLongArray(); + Team team = Team.all[jsonData.getInt("team", 0)]; + TeamData out = new TeamData(team, EnumSet.of(new Team[]{})); + out.brokenBlocks = new LongQueue(blocks); + return out; + } + }); + + setSerializer(ItemStack.class, new Serializer(){ + @Override + public void write(Json json, ItemStack object, Class knownType){ + json.writeObjectStart(); + json.writeValue("item", object.item); + json.writeValue("amount", object.amount); + json.writeObjectEnd(); + } + + @Override + public ItemStack read(Json json, JsonValue jsonData, Class type){ + return new ItemStack(json.getSerializer(Item.class).read(json, jsonData.get("item"), Item.class), jsonData.getInt("amount")); + } + }); }}; public static String write(Object object){ diff --git a/core/src/io/anuke/mindustry/io/MapIO.java b/core/src/io/anuke/mindustry/io/MapIO.java index 8daf1a7e2a..066d87d488 100644 --- a/core/src/io/anuke/mindustry/io/MapIO.java +++ b/core/src/io/anuke/mindustry/io/MapIO.java @@ -1,20 +1,18 @@ package io.anuke.mindustry.io; -import io.anuke.arc.collection.StringMap; -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.io.CounterInputStream; -import io.anuke.mindustry.content.Blocks; -import io.anuke.mindustry.game.Team; -import io.anuke.mindustry.game.Version; -import io.anuke.mindustry.maps.Map; +import io.anuke.arc.collection.*; +import io.anuke.arc.files.*; +import io.anuke.arc.graphics.*; +import io.anuke.arc.graphics.Pixmap.*; +import io.anuke.arc.util.io.*; +import io.anuke.mindustry.content.*; +import io.anuke.mindustry.game.*; +import io.anuke.mindustry.maps.*; import io.anuke.mindustry.world.*; -import io.anuke.mindustry.world.blocks.storage.CoreBlock; +import io.anuke.mindustry.world.blocks.storage.*; import java.io.*; -import java.util.zip.InflaterInputStream; +import java.util.zip.*; import static io.anuke.mindustry.Vars.*; @@ -64,9 +62,8 @@ public class MapIO{ } public static Pixmap generatePreview(Map map) throws IOException{ - //by default, it does not have an enemy core or any other cores - map.tags.put("enemycore", "false"); - map.tags.put("othercore", "false"); + map.spawns = 0; + map.teams.clear(); try(InputStream is = new InflaterInputStream(map.file.read(bufferSize)); CounterInputStream counter = new CounterInputStream(is); DataInputStream stream = new DataInputStream(counter)){ SaveIO.readHeader(stream); @@ -93,15 +90,7 @@ public class MapIO{ public void setTeam(Team team){ super.setTeam(team); if(block instanceof CoreBlock){ - if(team != defaultTeam){ - //map must have other team's cores - map.tags.put("othercore", "true"); - } - - if(team == waveTeam){ - //map must have default enemy team's core - map.tags.put("enemycore", "true"); - } + map.teams.add(team.ordinal()); } } }; @@ -127,6 +116,9 @@ public class MapIO{ }else{ floors.drawPixel(x, floors.getHeight() - 1 - y, colorFor(content.block(floorID), Blocks.air, Blocks.air, Team.none)); } + if(content.block(overlayID) == Blocks.spawn){ + map.spawns ++; + } return tile; } })); diff --git a/core/src/io/anuke/mindustry/io/SaveFileReader.java b/core/src/io/anuke/mindustry/io/SaveFileReader.java index 8384aca50e..a969776896 100644 --- a/core/src/io/anuke/mindustry/io/SaveFileReader.java +++ b/core/src/io/anuke/mindustry/io/SaveFileReader.java @@ -14,7 +14,9 @@ public abstract class SaveFileReader{ protected final DataOutputStream dataBytes = new DataOutputStream(byteOutput); protected final ReusableByteOutStream byteOutputSmall = new ReusableByteOutStream(); protected final DataOutputStream dataBytesSmall = new DataOutputStream(byteOutputSmall); - protected final ObjectMap fallback = ObjectMap.of(); + protected final ObjectMap fallback = ObjectMap.of( + + ); protected void region(String name, DataInput stream, CounterInputStream counter, IORunner cons) throws IOException{ counter.resetCount(); diff --git a/core/src/io/anuke/mindustry/io/SaveIO.java b/core/src/io/anuke/mindustry/io/SaveIO.java index 916c4ad414..cb79c0222d 100644 --- a/core/src/io/anuke/mindustry/io/SaveIO.java +++ b/core/src/io/anuke/mindustry/io/SaveIO.java @@ -6,6 +6,7 @@ import io.anuke.arc.util.io.CounterInputStream; import io.anuke.arc.util.io.FastDeflaterOutputStream; import io.anuke.mindustry.Vars; import io.anuke.mindustry.io.versions.Save1; +import io.anuke.mindustry.io.versions.Save2; import io.anuke.mindustry.world.WorldContext; import java.io.*; @@ -18,7 +19,7 @@ public class SaveIO{ /** Format header. This is the string 'MSAV' in ASCII. */ public static final byte[] header = {77, 83, 65, 86}; public static final IntMap versions = new IntMap<>(); - public static final Array versionArray = Array.with(new Save1()); + public static final Array versionArray = Array.with(new Save1(), new Save2()); static{ for(SaveVersion version : versionArray){ diff --git a/core/src/io/anuke/mindustry/io/SaveVersion.java b/core/src/io/anuke/mindustry/io/SaveVersion.java index 1071fc9b08..b4f700a582 100644 --- a/core/src/io/anuke/mindustry/io/SaveVersion.java +++ b/core/src/io/anuke/mindustry/io/SaveVersion.java @@ -1,15 +1,14 @@ package io.anuke.mindustry.io; -import io.anuke.arc.collection.Array; -import io.anuke.arc.collection.StringMap; -import io.anuke.arc.util.Time; -import io.anuke.arc.util.io.CounterInputStream; -import io.anuke.mindustry.entities.Entities; -import io.anuke.mindustry.entities.EntityGroup; +import io.anuke.arc.collection.*; +import io.anuke.arc.util.*; +import io.anuke.arc.util.io.*; +import io.anuke.mindustry.entities.*; import io.anuke.mindustry.entities.traits.*; import io.anuke.mindustry.game.*; -import io.anuke.mindustry.maps.Map; -import io.anuke.mindustry.type.ContentType; +import io.anuke.mindustry.gen.*; +import io.anuke.mindustry.maps.*; +import io.anuke.mindustry.type.*; import io.anuke.mindustry.world.*; import java.io.*; @@ -19,6 +18,9 @@ import static io.anuke.mindustry.Vars.*; public abstract class SaveVersion extends SaveFileReader{ public final int version; + //HACK stores the last read build of the save file, valid after read meta call + protected int lastReadBuild; + public SaveVersion(int version){ this.version = version; } @@ -76,7 +78,9 @@ public abstract class SaveVersion extends SaveFileReader{ state.wavetime = map.getFloat("wavetime", state.rules.waveSpacing); state.stats = JsonIO.read(Stats.class, map.get("stats", "{}")); state.rules = JsonIO.read(Rules.class, map.get("rules", "{}")); - if(state.rules.spawns.isEmpty()) state.rules.spawns = DefaultWaves.get(); + if(state.rules.spawns.isEmpty()) state.rules.spawns = defaultWaves.get(); + lastReadBuild = map.getInt("build", -1); + Map worldmap = world.maps.byName(map.get("mapname", "\\\\\\")); world.setMap(worldmap == null ? new Map(StringMap.of( "name", map.get("mapname", "Unknown"), @@ -92,13 +96,13 @@ public abstract class SaveVersion extends SaveFileReader{ //floor + overlay for(int i = 0; i < world.width() * world.height(); i++){ - Tile tile = world.tile(i % world.width(), i / world.width()); + Tile tile = world.rawTile(i % world.width(), i / world.width()); stream.writeShort(tile.floorID()); stream.writeShort(tile.overlayID()); 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()); + Tile nextTile = world.rawTile(j % world.width(), j / world.width()); if(nextTile.floorID() != tile.floorID() || nextTile.overlayID() != tile.overlayID()){ break; @@ -113,7 +117,7 @@ public abstract class SaveVersion extends SaveFileReader{ //blocks for(int i = 0; i < world.width() * world.height(); i++){ - Tile tile = world.tile(i % world.width(), i / world.width()); + Tile tile = world.rawTile(i % world.width(), i / world.width()); stream.writeShort(tile.blockID()); if(tile.entity != null){ @@ -126,7 +130,7 @@ public abstract class SaveVersion extends SaveFileReader{ 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()); + Tile nextTile = world.rawTile(j % world.width(), j / world.width()); if(nextTile.blockID() != tile.blockID()){ break; @@ -220,7 +224,7 @@ public abstract class SaveVersion extends SaveFileReader{ SaveTrait save = (SaveTrait)entity; //each entity is a separate chunk. writeChunk(stream, true, out -> { - out.writeByte(save.getTypeID()); + out.writeByte(save.getTypeID().id); out.writeByte(save.version()); save.writeSave(out); }); @@ -239,7 +243,7 @@ public abstract class SaveVersion extends SaveFileReader{ readChunk(stream, true, in -> { byte typeid = in.readByte(); byte version = in.readByte(); - SaveTrait trait = (SaveTrait)TypeTrait.getTypeByID(typeid).get(); + SaveTrait trait = (SaveTrait)content.getByID(ContentType.typeid, typeid).constructor.get(); trait.readSave(in, version); }); } @@ -247,7 +251,6 @@ public abstract class SaveVersion extends SaveFileReader{ } public void readContentHeader(DataInput stream) throws IOException{ - byte mapped = stream.readByte(); MappableContent[][] map = new MappableContent[ContentType.values().length][0]; @@ -287,4 +290,17 @@ public abstract class SaveVersion extends SaveFileReader{ } } } + + /** sometimes it's necessary to remap IDs after the content header is read.*/ + public void remapContent(){ + for(Team team : Team.all){ + if(state.teams.isActive(team)){ + LongQueue queue = state.teams.get(team).brokenBlocks; + for(int i = 0; i < queue.size; i++){ + //remap broken block IDs + queue.set(i, BrokenBlock.block(queue.get(i), content.block(BrokenBlock.block(queue.get(i))).id)); + } + } + } + } } diff --git a/core/src/io/anuke/mindustry/io/TypeIO.java b/core/src/io/anuke/mindustry/io/TypeIO.java index c3dc0be2d3..97f92584f2 100644 --- a/core/src/io/anuke/mindustry/io/TypeIO.java +++ b/core/src/io/anuke/mindustry/io/TypeIO.java @@ -86,15 +86,15 @@ public class TypeIO{ @WriteClass(BaseUnit.class) public static void writeBaseUnit(ByteBuffer buffer, BaseUnit unit){ - buffer.put((byte)unitGroups[unit.getTeam().ordinal()].getID()); + buffer.put((byte)unit.getTeam().ordinal()); buffer.putInt(unit.getID()); } @ReadClass(BaseUnit.class) - public static BaseUnit writeBaseUnit(ByteBuffer buffer){ - byte gid = buffer.get(); + public static BaseUnit readBaseUnit(ByteBuffer buffer){ + byte tid = buffer.get(); int id = buffer.getInt(); - return (BaseUnit)Entities.getGroup(gid).getByID(id); + return unitGroups[tid].getByID(id); } @WriteClass(Tile.class) @@ -139,6 +139,10 @@ public class TypeIO{ int position = buffer.getInt(); BuildRequest currentRequest; + if(world.tile(position) == null){ + continue; + } + if(type == 1){ //remove currentRequest = new BuildRequest(Pos.x(position), Pos.y(position)); }else{ //place @@ -193,6 +197,16 @@ public class TypeIO{ return Effects.getEffect(buffer.getShort()); } + @WriteClass(UnitType.class) + public static void writeUnitType(ByteBuffer buffer, UnitType effect){ + buffer.putShort(effect.id); + } + + @ReadClass(UnitType.class) + public static UnitType readUnitType(ByteBuffer buffer){ + return content.getByID(ContentType.unit, buffer.getShort()); + } + @WriteClass(Color.class) public static void writeColor(ByteBuffer buffer, Color color){ buffer.putInt(Color.rgba8888(color)); diff --git a/core/src/io/anuke/mindustry/io/versions/LegacyTypeTable.java b/core/src/io/anuke/mindustry/io/versions/LegacyTypeTable.java new file mode 100644 index 0000000000..6205313247 --- /dev/null +++ b/core/src/io/anuke/mindustry/io/versions/LegacyTypeTable.java @@ -0,0 +1,129 @@ +package io.anuke.mindustry.io.versions; + +import io.anuke.arc.function.Supplier; +import io.anuke.mindustry.entities.bullet.Bullet; +import io.anuke.mindustry.entities.effect.*; +import io.anuke.mindustry.entities.type.Player; +import io.anuke.mindustry.entities.type.base.*; + +/* +Latest data: [build 81] + +0 = Player +1 = Fire +2 = Puddle +3 = Draug +4 = Spirit +5 = Phantom +6 = Dagger +7 = Crawler +8 = Titan +9 = Fortress +10 = Eruptor +11 = Wraith +12 = Ghoul +13 = Revenant + +Before removal of lightining/bullet: [build 80] + +0 = Player +1 = Fire +2 = Puddle +3 = Bullet +4 = Lightning +5 = Draug +6 = Spirit +7 = Phantom +8 = Dagger +9 = Crawler +10 = Titan +11 = Fortress +12 = Eruptor +13 = Wraith +14 = Ghoul +15 = Revenant + +Before addition of new units: [build 79 and below] + +0 = Player +1 = Fire +2 = Puddle +3 = Bullet +4 = Lightning +5 = Spirit +6 = Dagger +7 = Crawler +8 = Titan +9 = Fortress +10 = Eruptor +11 = Wraith +12 = Ghoul +13 = Phantom +14 = Revenant + */ +public class LegacyTypeTable{ + private static final Supplier[] build81Table = { + Player::new, + Fire::new, + Puddle::new, + Draug::new, + Spirit::new, + Phantom::new, + Dagger::new, + Crawler::new, + Titan::new, + Fortress::new, + Eruptor::new, + Wraith::new, + Ghoul::new, + Revenant::new + }; + + private static final Supplier[] build80Table = { + Player::new, + Fire::new, + Puddle::new, + Bullet::new, //TODO reading these may crash + Lightning::new, + Draug::new, + Spirit::new, + Phantom::new, + Dagger::new, + Crawler::new, + Titan::new, + Fortress::new, + Eruptor::new, + Wraith::new, + Ghoul::new, + Revenant::new + }; + + private static final Supplier[] build79Table = { + Player::new, + Fire::new, + Puddle::new, + Bullet::new, //TODO reading these may crash + Lightning::new, + Spirit::new, + Dagger::new, + Crawler::new, + Titan::new, + Fortress::new, + Eruptor::new, + Wraith::new, + Ghoul::new, + Phantom::new, + Revenant::new + }; + + public static Supplier[] getTable(int build){ + if(build == -1 || build == 81){ + //return most recent one since that's probably is; not guaranteed + return build81Table; + }else if(build == 80){ + return build80Table; + }else{ + return build79Table; + } + } +} diff --git a/core/src/io/anuke/mindustry/io/versions/Save1.java b/core/src/io/anuke/mindustry/io/versions/Save1.java index f9ea40b8ce..545ae99eb2 100644 --- a/core/src/io/anuke/mindustry/io/versions/Save1.java +++ b/core/src/io/anuke/mindustry/io/versions/Save1.java @@ -1,10 +1,34 @@ package io.anuke.mindustry.io.versions; +import io.anuke.arc.function.Supplier; +import io.anuke.mindustry.entities.traits.SaveTrait; import io.anuke.mindustry.io.SaveVersion; +import java.io.DataInput; +import java.io.IOException; + public class Save1 extends SaveVersion{ public Save1(){ super(1); } + + @Override + public void readEntities(DataInput stream) throws IOException{ + Supplier[] table = LegacyTypeTable.getTable(lastReadBuild); + + byte groups = stream.readByte(); + + for(int i = 0; i < groups; i++){ + int amount = stream.readInt(); + for(int j = 0; j < amount; j++){ + readChunk(stream, true, in -> { + byte typeid = in.readByte(); + byte version = in.readByte(); + SaveTrait trait = (SaveTrait)table[typeid].get(); + trait.readSave(in, version); + }); + } + } + } } diff --git a/core/src/io/anuke/mindustry/io/versions/Save2.java b/core/src/io/anuke/mindustry/io/versions/Save2.java new file mode 100644 index 0000000000..66d61964c5 --- /dev/null +++ b/core/src/io/anuke/mindustry/io/versions/Save2.java @@ -0,0 +1,9 @@ +package io.anuke.mindustry.io.versions; + +import io.anuke.mindustry.io.SaveVersion; + +public class Save2 extends SaveVersion{ + public Save2(){ + super(2); + } +} diff --git a/core/src/io/anuke/mindustry/maps/Map.java b/core/src/io/anuke/mindustry/maps/Map.java index 07ed0efb1d..89165b14c8 100644 --- a/core/src/io/anuke/mindustry/maps/Map.java +++ b/core/src/io/anuke/mindustry/maps/Map.java @@ -1,13 +1,15 @@ package io.anuke.mindustry.maps; import io.anuke.arc.Core; -import io.anuke.arc.collection.StringMap; +import io.anuke.arc.collection.*; import io.anuke.arc.files.FileHandle; import io.anuke.arc.graphics.Texture; import io.anuke.mindustry.Vars; -import io.anuke.mindustry.game.DefaultWaves; -import io.anuke.mindustry.game.Rules; +import io.anuke.mindustry.game.*; import io.anuke.mindustry.io.JsonIO; +import io.anuke.mindustry.maps.filters.*; + +import static io.anuke.mindustry.Vars.world; public class Map implements Comparable{ /** Whether this is a custom map. */ @@ -24,6 +26,10 @@ public class Map implements Comparable{ public Texture texture; /** Build that this map was created in. -1 = unknown or custom build. */ public int build; + /** All teams present on this map.*/ + public IntSet teams = new IntSet(); + /** Number of enemy spawns on this map.*/ + public int spawns = 0; public Map(FileHandle file, int width, int height, StringMap tags, boolean custom, int version, int build){ this.custom = custom; @@ -56,23 +62,19 @@ public class Map implements Comparable{ Vars.data.modified(); } - /** This creates a new instance.*/ + /** This creates a new instance of Rules.*/ public Rules rules(){ Rules result = JsonIO.read(Rules.class, tags.get("rules", "{}")); - if(result.spawns.isEmpty()) result.spawns = DefaultWaves.get(); + if(result.spawns.isEmpty()) result.spawns = Vars.defaultWaves.get(); return result; } - /** Whether this map has a core of the enemy 'wave' team. Default: true. - * Used for checking Attack mode validity.*/ - public boolean hasEnemyCore(){ - return tags.get("enemycore", "true").equals("true"); - } - - /** Whether this map has a core of any team except the default player team. Default: true. - * Used for checking PvP mode validity.*/ - public boolean hasOtherCores(){ - return tags.get("othercore", "true").equals("true"); + /** Returns the generation filters that this map uses on load.*/ + public Array filters(){ + if(build != -1 && build < 83 && tags.get("genfilters", "").isEmpty()){ + return Array.with(); + } + return world.maps.readFilters(tags.get("genfilters", "")); } public String author(){ diff --git a/core/src/io/anuke/mindustry/maps/Maps.java b/core/src/io/anuke/mindustry/maps/Maps.java index 03597baa48..80cce4c0b5 100644 --- a/core/src/io/anuke/mindustry/maps/Maps.java +++ b/core/src/io/anuke/mindustry/maps/Maps.java @@ -1,24 +1,26 @@ package io.anuke.mindustry.maps; -import io.anuke.arc.Core; +import io.anuke.arc.*; import io.anuke.arc.collection.*; -import io.anuke.arc.files.FileHandle; -import io.anuke.arc.function.ExceptionRunnable; -import io.anuke.arc.graphics.Texture; +import io.anuke.arc.files.*; +import io.anuke.arc.function.*; +import io.anuke.arc.graphics.*; import io.anuke.arc.util.*; -import io.anuke.arc.util.serialization.Json; -import io.anuke.mindustry.game.SpawnGroup; -import io.anuke.mindustry.io.LegacyMapIO; -import io.anuke.mindustry.io.MapIO; +import io.anuke.arc.util.serialization.*; +import io.anuke.mindustry.content.*; +import io.anuke.mindustry.game.*; +import io.anuke.mindustry.io.*; +import io.anuke.mindustry.maps.filters.*; +import io.anuke.mindustry.world.*; +import io.anuke.mindustry.world.blocks.storage.*; -import java.io.IOException; -import java.io.StringWriter; +import java.io.*; import static io.anuke.mindustry.Vars.*; public class Maps implements Disposable{ /** List of all built-in maps. Filenames only. */ - private static final String[] defaultMapNames = {"fortress", "labyrinth", "islands"}; + private static String[] defaultMapNames = {"maze", "fortress", "labyrinth", "islands", "tendrils", "caldera", "wasteland", "shattered", "fork", "triad", "veins", "glacier"}; /** All maps stored in an ordered array. */ private Array maps = new Array<>(); /** Serializer for meta. */ @@ -108,6 +110,24 @@ public class Maps implements Disposable{ MapIO.writeMap(file, map); if(!headless){ + //reset attributes + map.teams.clear(); + map.spawns = 0; + + for(int x = 0; x < map.width; x++){ + for(int y = 0; y < map.height; y++){ + Tile tile = world.getTiles()[x][y]; + + if(tile.block() instanceof CoreBlock){ + map.teams.add(tile.getTeamID()); + } + + if(tile.overlay() == Blocks.spawn){ + map.spawns ++; + } + } + } + map.texture = new Texture(MapIO.generatePreview(world.getTiles())); } maps.add(map); @@ -162,6 +182,48 @@ public class Maps implements Disposable{ map.file.delete(); } + /** Reads JSON of filters, returning a new default array if not found.*/ + @SuppressWarnings("unchecked") + public Array readFilters(String str){ + if(str == null || str.isEmpty()){ + //create default filters list + Array filters = Array.with( + new ScatterFilter(){{ + flooronto = Blocks.stone; + block = Blocks.rock; + }}, + new ScatterFilter(){{ + flooronto = Blocks.shale; + block = Blocks.shaleBoulder; + }}, + new ScatterFilter(){{ + flooronto = Blocks.snow; + block = Blocks.snowrock; + }}, + new ScatterFilter(){{ + flooronto = Blocks.ice; + block = Blocks.snowrock; + }}, + new ScatterFilter(){{ + flooronto = Blocks.sand; + block = Blocks.sandBoulder; + }} + ); + + int index = 0; + for(Block block : new Block[]{Blocks.oreCopper, Blocks.oreLead, Blocks.oreCoal, Blocks.oreTitanium, Blocks.oreThorium}){ + OreFilter filter = new OreFilter(); + filter.threshold += index ++ * 0.019f; + filter.ore = block; + filters.add(filter); + } + + return filters; + }else{ + return JsonIO.read(Array.class, str); + } + } + public String writeWaves(Array groups){ if(groups == null){ return "[]"; @@ -234,7 +296,7 @@ public class Maps implements Disposable{ } maps.add(map); - maps.sort(); + //maps.sort(); } private void loadCustomMaps(){ diff --git a/core/src/io/anuke/mindustry/maps/filters/BlendFilter.java b/core/src/io/anuke/mindustry/maps/filters/BlendFilter.java new file mode 100644 index 0000000000..f1f16e7800 --- /dev/null +++ b/core/src/io/anuke/mindustry/maps/filters/BlendFilter.java @@ -0,0 +1,48 @@ +package io.anuke.mindustry.maps.filters; + +import io.anuke.arc.math.*; +import io.anuke.mindustry.content.*; +import io.anuke.mindustry.maps.filters.FilterOption.*; +import io.anuke.mindustry.world.*; + +import static io.anuke.mindustry.maps.filters.FilterOption.*; + +public class BlendFilter extends GenerateFilter{ + float radius = 2f; + Block block = Blocks.stone, floor = Blocks.ice, ignore = Blocks.air; + + { + buffered = true; + options( + new SliderOption("radius", () -> radius, f -> radius = f, 1f, 10f), + new BlockOption("block", () -> block, b -> block = b, anyOptional), + new BlockOption("floor", () -> floor, b -> floor = b, floorsOnly), + new BlockOption("ignore", () -> ignore, b -> ignore = b, floorsOptional) + ); + } + + @Override + public void apply(){ + if(in.floor == block || block == Blocks.air || in.floor == ignore) return; + + int rad = (int)radius; + boolean found = false; + + outer: + for(int x = -rad; x <= rad; x++){ + for(int y = -rad; y <= rad; y++){ + if(Mathf.dst2(x, y) > rad*rad) continue; + Tile tile = in.tile(in.x + x, in.y + y); + + if(tile.floor() == block || tile.block() == block || tile.overlay() == block){ + found = true; + break outer; + } + } + } + + if(found){ + in.floor = floor; + } + } +} diff --git a/core/src/io/anuke/mindustry/maps/filters/ClearFilter.java b/core/src/io/anuke/mindustry/maps/filters/ClearFilter.java new file mode 100644 index 0000000000..418f99bebc --- /dev/null +++ b/core/src/io/anuke/mindustry/maps/filters/ClearFilter.java @@ -0,0 +1,24 @@ +package io.anuke.mindustry.maps.filters; + +import io.anuke.mindustry.content.*; +import io.anuke.mindustry.world.*; + +import static io.anuke.mindustry.maps.filters.FilterOption.*; + +public class ClearFilter extends GenerateFilter{ + protected Block block = Blocks.air; + + { + options( + new BlockOption("block", () -> block, b -> block = b, wallsOnly) + ); + } + + @Override + public void apply(){ + + if(in.block == block){ + in.block = Blocks.air; + } + } +} diff --git a/core/src/io/anuke/mindustry/maps/filters/DistortFilter.java b/core/src/io/anuke/mindustry/maps/filters/DistortFilter.java new file mode 100644 index 0000000000..4da9afaefb --- /dev/null +++ b/core/src/io/anuke/mindustry/maps/filters/DistortFilter.java @@ -0,0 +1,26 @@ +package io.anuke.mindustry.maps.filters; + +import io.anuke.mindustry.maps.filters.FilterOption.*; +import io.anuke.mindustry.world.*; +import io.anuke.mindustry.world.blocks.*; + +public class DistortFilter extends GenerateFilter{ + float scl = 40, mag = 5; + + { + buffered = true; + options( + new SliderOption("scale", () -> scl, f -> scl = f, 1f, 400f), + new SliderOption("mag", () -> mag, f -> mag = f, 0.5f, 100f) + ); + } + + @Override + public void apply(){ + Tile tile = in.tile(in.x + noise(in.x, in.y, scl, mag) - mag / 2f, in.y + noise(in.x, in.y + o, scl, mag) - mag / 2f); + + in.floor = tile.floor(); + if(!tile.block().synthetic() && !in.block.synthetic()) in.block = tile.block(); + if(!((Floor)in.floor).isLiquid) in.ore = tile.overlay(); + } +} diff --git a/core/src/io/anuke/mindustry/editor/generation/FilterOption.java b/core/src/io/anuke/mindustry/maps/filters/FilterOption.java similarity index 60% rename from core/src/io/anuke/mindustry/editor/generation/FilterOption.java rename to core/src/io/anuke/mindustry/maps/filters/FilterOption.java index 7034fb5467..7874f85c5b 100644 --- a/core/src/io/anuke/mindustry/editor/generation/FilterOption.java +++ b/core/src/io/anuke/mindustry/maps/filters/FilterOption.java @@ -1,14 +1,16 @@ -package io.anuke.mindustry.editor.generation; +package io.anuke.mindustry.maps.filters; -import io.anuke.arc.Core; + +import io.anuke.arc.*; 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.arc.scene.style.*; +import io.anuke.arc.scene.ui.*; +import io.anuke.arc.scene.ui.layout.*; +import io.anuke.mindustry.*; +import io.anuke.mindustry.content.*; +import io.anuke.mindustry.ui.dialogs.*; +import io.anuke.mindustry.world.*; +import io.anuke.mindustry.world.Block.*; import io.anuke.mindustry.world.blocks.*; import static io.anuke.mindustry.Vars.updateEditorOnChange; @@ -16,32 +18,40 @@ import static io.anuke.mindustry.Vars.updateEditorOnChange; public abstract class FilterOption{ public static final Predicate floorsOnly = b -> (b instanceof Floor && !(b instanceof OverlayFloor)) && 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 floorsOptional = b -> b == Blocks.air || ((b instanceof Floor && !(b instanceof OverlayFloor)) && Core.atlas.isFound(b.icon(Icon.full))); + public static final Predicate wallsOptional = b -> b == Blocks.air || ((!b.synthetic() && !(b instanceof Floor)) && Core.atlas.isFound(b.icon(Icon.full))); + public static final Predicate wallsOresOptional = b -> b == Blocks.air || (((!b.synthetic() && !(b instanceof Floor)) || (b instanceof OverlayFloor)) && Core.atlas.isFound(b.icon(Icon.full))); public static final Predicate oresOnly = b -> b instanceof OverlayFloor && Core.atlas.isFound(b.icon(Icon.full)); + public static final Predicate anyOptional = b -> floorsOnly.test(b) || wallsOnly.test(b) || oresOnly.test(b) || b == Blocks.air; public abstract void build(Table table); - public Runnable changed = () -> { - }; + public Runnable changed = () -> {}; static class SliderOption extends FilterOption{ final String name; final FloatProvider getter; final FloatConsumer setter; - final float min, max; + final float min, max, step; SliderOption(String name, FloatProvider getter, FloatConsumer setter, float min, float max){ + this(name, getter, setter, min, max, (max - min) / 200); + } + + SliderOption(String name, FloatProvider getter, FloatConsumer setter, float min, float max, float step){ this.name = name; this.getter = getter; this.setter = setter; this.min = min; this.max = max; + this.step = step; } @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 slider = table.addSlider(min, max, step, setter).growX().get(); slider.setValue(getter.get()); if(updateEditorOnChange){ slider.changed(changed); @@ -66,14 +76,15 @@ public abstract class FilterOption{ @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), () -> { + table.addButton(b -> b.addImage(supplier.get().icon(Icon.small)).update(i -> ((TextureRegionDrawable)i.getDrawable()) + .setRegion(supplier.get() == Blocks.air ? Core.atlas.find("icon-none") : 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(() -> { + dialog.cont.addImage(block == Blocks.air ? Core.atlas.find("icon-none-small") : block.icon(Icon.medium)).size(8 * 4).pad(3).get().clicked(() -> { consumer.accept(block); dialog.hide(); changed.run(); diff --git a/core/src/io/anuke/mindustry/editor/generation/GenerateFilter.java b/core/src/io/anuke/mindustry/maps/filters/GenerateFilter.java similarity index 60% rename from core/src/io/anuke/mindustry/editor/generation/GenerateFilter.java rename to core/src/io/anuke/mindustry/maps/filters/GenerateFilter.java index 9105a7b4e8..2ab84d2864 100644 --- a/core/src/io/anuke/mindustry/editor/generation/GenerateFilter.java +++ b/core/src/io/anuke/mindustry/maps/filters/GenerateFilter.java @@ -1,25 +1,54 @@ -package io.anuke.mindustry.editor.generation; +package io.anuke.mindustry.maps.filters; -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.content.Blocks; -import io.anuke.mindustry.editor.MapEditor; -import io.anuke.mindustry.editor.MapGenerateDialog.GenTile; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.blocks.Floor; +import io.anuke.arc.*; +import io.anuke.arc.math.*; +import io.anuke.arc.scene.ui.*; +import io.anuke.arc.util.*; +import io.anuke.arc.util.noise.*; +import io.anuke.mindustry.content.*; +import io.anuke.mindustry.world.*; +import io.anuke.mindustry.world.blocks.*; public abstract class GenerateFilter{ protected transient float o = (float)(Math.random() * 10000000.0); protected transient long seed; protected transient GenerateInput in; - public FilterOption[] options; + public transient boolean buffered = false; + public transient FilterOption[] options; + public final void apply(GenerateInput in){ + this.in = in; + apply(); + //remove extra ores on liquids + if(((Floor)in.floor).isLiquid){ + in.ore = Blocks.air; + } + } + + /** sets up the options; this is necessary since the constructor can't access subclass variables. */ + protected void options(FilterOption... options){ + this.options = options; + } + + /** apply the actual filter on the input */ protected abstract void apply(); + /** draw any additional guides */ + public void draw(Image image){} + + /** localized display name */ + public String name(){ + return Core.bundle.get("filter." + getClass().getSimpleName().toLowerCase().replace("filter", ""), getClass().getSimpleName().replace("Filter", "")); + } + + /** set the seed to a random number */ + public void randomize(){ + seed = Mathf.random(99999999); + } + + //utility generation functions + protected float noise(float x, float y, float scl, float mag){ return (float)in.noise.octaveNoise2D(1f, 0f, 1f / scl, x + o, y + o) * mag; } @@ -32,68 +61,45 @@ public abstract class GenerateFilter{ 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(); - //remove extra ores on liquids - if(((Floor)in.floor).isLiquid){ - in.ore = Blocks.air; - } - } - + /** an input for generating at a certain coordinate. should only be instantiated once. */ public static class GenerateInput{ - public Floor srcfloor; - public Block srcblock; - public Block srcore; - public int x, y, width, height, scaling; - public MapEditor editor; + /** input size parameters */ + public int x, y, width, height; + + /** output parameters */ 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; + public void apply(int x, int y, Block floor, Block block, Block ore){ + this.floor = floor; + this.block = block; + this.ore = ore; this.x = x; this.y = y; } - public void setFilter(GenerateFilter filter, int width, int height, int scaling, TileProvider buffer){ + public void begin(GenerateFilter filter, int width, int height, TileProvider buffer){ this.buffer = buffer; this.width = width; this.height = height; - this.scaling = scaling; noise.setSeed(filter.seed); pnoise.setSeed((int)(filter.seed + 1)); } - GenTile tile(float x, float y){ + Tile tile(float x, float y){ return buffer.get(Mathf.clamp((int)x, 0, width - 1), Mathf.clamp((int)y, 0, height - 1)); } public interface TileProvider{ - GenTile get(int x, int y); + Tile get(int x, int y); } } } diff --git a/core/src/io/anuke/mindustry/editor/generation/MedianFilter.java b/core/src/io/anuke/mindustry/maps/filters/MedianFilter.java similarity index 73% rename from core/src/io/anuke/mindustry/editor/generation/MedianFilter.java rename to core/src/io/anuke/mindustry/maps/filters/MedianFilter.java index 548b861f8c..9cc4606d20 100644 --- a/core/src/io/anuke/mindustry/editor/generation/MedianFilter.java +++ b/core/src/io/anuke/mindustry/maps/filters/MedianFilter.java @@ -1,9 +1,9 @@ -package io.anuke.mindustry.editor.generation; +package io.anuke.mindustry.maps.filters; -import io.anuke.arc.collection.IntArray; -import io.anuke.arc.math.Mathf; -import io.anuke.mindustry.editor.MapGenerateDialog.GenTile; -import io.anuke.mindustry.editor.generation.FilterOption.SliderOption; +import io.anuke.arc.collection.*; +import io.anuke.arc.math.*; +import io.anuke.mindustry.maps.filters.FilterOption.*; +import io.anuke.mindustry.world.*; import static io.anuke.mindustry.Vars.content; @@ -13,6 +13,7 @@ public class MedianFilter extends GenerateFilter{ IntArray blocks = new IntArray(), floors = new IntArray(); { + buffered = true; options( new SliderOption("radius", () -> radius, f -> radius = f, 1f, 12f), new SliderOption("percentile", () -> percentile, f -> percentile = f, 0f, 1f) @@ -28,9 +29,9 @@ public class MedianFilter extends GenerateFilter{ for(int y = -rad; y <= rad; y++){ if(Mathf.dst2(x, y) > rad*rad) continue; - GenTile tile = in.tile(in.x + x, in.y + y); - blocks.add(tile.block); - floors.add(tile.floor); + Tile tile = in.tile(in.x + x, in.y + y); + blocks.add(tile.block().id); + floors.add(tile.floor().id); } } diff --git a/core/src/io/anuke/mindustry/maps/filters/MirrorFilter.java b/core/src/io/anuke/mindustry/maps/filters/MirrorFilter.java new file mode 100644 index 0000000000..866dc791f1 --- /dev/null +++ b/core/src/io/anuke/mindustry/maps/filters/MirrorFilter.java @@ -0,0 +1,84 @@ +package io.anuke.mindustry.maps.filters; + +import io.anuke.arc.function.*; +import io.anuke.arc.graphics.g2d.*; +import io.anuke.arc.math.geom.*; +import io.anuke.arc.scene.ui.*; +import io.anuke.arc.scene.ui.layout.*; +import io.anuke.arc.util.*; +import io.anuke.mindustry.graphics.*; +import io.anuke.mindustry.maps.filters.FilterOption.*; +import io.anuke.mindustry.world.*; + +public class MirrorFilter extends GenerateFilter{ + private final Vector2 v1 = new Vector2(), v2 = new Vector2(), v3 = new Vector2(); + + int angle = 45; + + { + options(new SliderOption("angle", () -> angle, f -> angle = (int)f, 0, 360, 45)); + } + + @Override + protected void apply(){ + v1.trns(angle - 90, 1f); + v2.set(v1).scl(-1f); + + v1.add(in.width/2f, in.height/2f); + v2.add(in.width/2f, in.height/2f); + + v3.set(in.x, in.y); + + if(!left(v1, v2, v3)){ + mirror(v3, v1.x, v1.y, v2.x, v2.y); + Tile tile = in.tile(v3.x, v3.y); + in.floor = tile.floor(); + in.block = tile.block(); + in.ore = tile.overlay(); + } + } + + @Override + public void draw(Image image){ + super.draw(image); + + Vector2 vsize = Scaling.fit.apply(image.getDrawable().getMinWidth(), image.getDrawable().getMinHeight(), image.getWidth(), image.getHeight()); + float imageWidth = Math.max(vsize.x, vsize.y); + float imageHeight = Math.max(vsize.y, vsize.x); + + float size = Math.max(image.getWidth() *2, image.getHeight()*2); + Consumer clamper = v -> + v.clamp( + image.getX() + image.getWidth()/2f - imageWidth/2f, + image.getX() + image.getWidth()/2f + imageWidth/2f, + image.getY() + image.getHeight()/2f - imageHeight/2f, + image.getY() + image.getHeight()/2f + imageHeight/2f); + + clamper.accept(Tmp.v1.trns(angle - 90, size).add(image.getWidth()/2f + image.getX(), image.getHeight()/2f + image.getY())); + clamper.accept(Tmp.v2.set(Tmp.v1).sub(image.getWidth()/2f + image.getX(), image.getHeight()/2f + image.getY()).rotate(180f).add(image.getWidth()/2f + image.getX(), image.getHeight()/2f + image.getY())); + + Lines.stroke(Unit.dp.scl(3f), Pal.accent); + Lines.line(Tmp.v1.x, Tmp.v1.y, Tmp.v2.x, Tmp.v2.y); + Draw.reset(); + } + + void mirror(Vector2 p, float x0, float y0, float x1, float y1){ + //special case: uneven map mirrored at 45 degree angle + if(in.width != in.height && angle % 90 != 0){ + p.x = (p.x - in.width/2f) * -1 + in.width/2f; + p.y = (p.y - in.height/2f) * -1 + in.height/2f; + }else{ + float dx = x1 - x0; + float dy = y1 - y0; + + float a = (dx * dx - dy * dy) / (dx * dx + dy * dy); + float b = 2 * dx * dy / (dx * dx + dy * dy); + + p.set((a * (p.x - x0) + b * (p.y - y0) + x0), (b * (p.x - x0) - a * (p.y - y0) + y0)); + } + } + + boolean left(Vector2 a, Vector2 b, Vector2 c){ + return ((b.x - a.x)*(c.y - a.y) - (b.y - a.y)*(c.x - a.x)) > 0; + } +} diff --git a/core/src/io/anuke/mindustry/editor/generation/NoiseFilter.java b/core/src/io/anuke/mindustry/maps/filters/NoiseFilter.java similarity index 70% rename from core/src/io/anuke/mindustry/editor/generation/NoiseFilter.java rename to core/src/io/anuke/mindustry/maps/filters/NoiseFilter.java index 6a6871df91..90c60afc39 100644 --- a/core/src/io/anuke/mindustry/editor/generation/NoiseFilter.java +++ b/core/src/io/anuke/mindustry/maps/filters/NoiseFilter.java @@ -1,12 +1,12 @@ -package io.anuke.mindustry.editor.generation; +package io.anuke.mindustry.maps.filters; 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.maps.filters.FilterOption.BlockOption; +import io.anuke.mindustry.maps.filters.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; +import static io.anuke.mindustry.maps.filters.FilterOption.floorsOnly; +import static io.anuke.mindustry.maps.filters.FilterOption.wallsOnly; public class NoiseFilter extends GenerateFilter{ float scl = 40, threshold = 0.5f, octaves = 3f, falloff = 0.5f; @@ -29,7 +29,7 @@ public class NoiseFilter extends GenerateFilter{ if(noise > threshold){ in.floor = floor; - if(wallsOnly.test(in.srcblock)) in.block = block; + if(wallsOnly.test(in.block)) in.block = block; } } } diff --git a/core/src/io/anuke/mindustry/editor/generation/OreFilter.java b/core/src/io/anuke/mindustry/maps/filters/OreFilter.java similarity index 63% rename from core/src/io/anuke/mindustry/editor/generation/OreFilter.java rename to core/src/io/anuke/mindustry/maps/filters/OreFilter.java index c5af869165..8de308989a 100644 --- a/core/src/io/anuke/mindustry/editor/generation/OreFilter.java +++ b/core/src/io/anuke/mindustry/maps/filters/OreFilter.java @@ -1,15 +1,15 @@ -package io.anuke.mindustry.editor.generation; +package io.anuke.mindustry.maps.filters; import io.anuke.mindustry.content.Blocks; -import io.anuke.mindustry.editor.generation.FilterOption.SliderOption; +import io.anuke.mindustry.maps.filters.FilterOption.SliderOption; import io.anuke.mindustry.world.Block; -import static io.anuke.mindustry.editor.generation.FilterOption.BlockOption; -import static io.anuke.mindustry.editor.generation.FilterOption.oresOnly; +import static io.anuke.mindustry.maps.filters.FilterOption.BlockOption; +import static io.anuke.mindustry.maps.filters.FilterOption.oresOnly; public class OreFilter extends GenerateFilter{ - float scl = 40, threshold = 0.8f, octaves = 3f, falloff = 0.5f; - Block ore = Blocks.oreCopper; + public float scl = 40, threshold = 0.75f, octaves = 2f, falloff = 0.4f; + public Block ore = Blocks.oreCopper; { options( @@ -25,7 +25,7 @@ public class OreFilter extends GenerateFilter{ public void apply(){ float noise = noise(in.x, in.y, scl, 1f, octaves, falloff); - if(noise > threshold){ + if(noise > threshold && in.ore != Blocks.spawn){ in.ore = ore; } } diff --git a/core/src/io/anuke/mindustry/editor/generation/RiverNoiseFilter.java b/core/src/io/anuke/mindustry/maps/filters/RiverNoiseFilter.java similarity index 71% rename from core/src/io/anuke/mindustry/editor/generation/RiverNoiseFilter.java rename to core/src/io/anuke/mindustry/maps/filters/RiverNoiseFilter.java index 2cfb256b41..1af7165157 100644 --- a/core/src/io/anuke/mindustry/editor/generation/RiverNoiseFilter.java +++ b/core/src/io/anuke/mindustry/maps/filters/RiverNoiseFilter.java @@ -1,12 +1,12 @@ -package io.anuke.mindustry.editor.generation; +package io.anuke.mindustry.maps.filters; 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.maps.filters.FilterOption.BlockOption; +import io.anuke.mindustry.maps.filters.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; +import static io.anuke.mindustry.maps.filters.FilterOption.floorsOnly; +import static io.anuke.mindustry.maps.filters.FilterOption.wallsOnly; public class RiverNoiseFilter extends GenerateFilter{ float scl = 40, threshold = 0f, threshold2 = 0.1f; @@ -15,8 +15,8 @@ public class RiverNoiseFilter extends GenerateFilter{ { 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 SliderOption("threshold", () -> threshold, f -> threshold = f, -1f, 0.3f), + new SliderOption("threshold2", () -> threshold2, f -> threshold2 = f, -1f, 0.3f), new BlockOption("block", () -> block, b -> block = b, wallsOnly), new BlockOption("floor", () -> floor, b -> floor = b, floorsOnly), new BlockOption("floor2", () -> floor2, b -> floor2 = b, floorsOnly) @@ -30,7 +30,7 @@ public class RiverNoiseFilter extends GenerateFilter{ if(noise >= threshold){ in.floor = floor; - if(in.srcblock.solid){ + if(in.block.solid){ in.block = block; } diff --git a/core/src/io/anuke/mindustry/maps/filters/ScatterFilter.java b/core/src/io/anuke/mindustry/maps/filters/ScatterFilter.java new file mode 100644 index 0000000000..3c00823075 --- /dev/null +++ b/core/src/io/anuke/mindustry/maps/filters/ScatterFilter.java @@ -0,0 +1,38 @@ +package io.anuke.mindustry.maps.filters; + +import io.anuke.mindustry.content.Blocks; +import io.anuke.mindustry.maps.filters.FilterOption.BlockOption; +import io.anuke.mindustry.maps.filters.FilterOption.SliderOption; +import io.anuke.mindustry.world.Block; + +import static io.anuke.mindustry.maps.filters.FilterOption.*; + +public class ScatterFilter extends GenerateFilter{ + protected float chance = 0.014f; + protected Block flooronto = Blocks.air, floor = Blocks.air, block = Blocks.air; + + { + options( + new SliderOption("chance", () -> chance, f -> chance = f, 0f, 1f), + new BlockOption("flooronto", () -> flooronto, b -> flooronto = b, floorsOptional), + new BlockOption("floor", () -> floor, b -> floor = b, floorsOptional), + new BlockOption("block", () -> block, b -> block = b, wallsOresOptional) + ); + } + + @Override + public void apply(){ + + if(block != Blocks.air && (in.floor == flooronto || flooronto == Blocks.air) && in.block == Blocks.air && chance() <= chance){ + if(!block.isOverlay()){ + in.block = block; + }else{ + in.ore = block; + } + } + + if(floor != Blocks.air && (in.floor == flooronto || flooronto == Blocks.air) && chance() <= chance){ + in.floor = floor; + } + } +} diff --git a/core/src/io/anuke/mindustry/editor/generation/TerrainFilter.java b/core/src/io/anuke/mindustry/maps/filters/TerrainFilter.java similarity index 73% rename from core/src/io/anuke/mindustry/editor/generation/TerrainFilter.java rename to core/src/io/anuke/mindustry/maps/filters/TerrainFilter.java index ab8e07c3cb..6082616494 100644 --- a/core/src/io/anuke/mindustry/editor/generation/TerrainFilter.java +++ b/core/src/io/anuke/mindustry/maps/filters/TerrainFilter.java @@ -1,13 +1,13 @@ -package io.anuke.mindustry.editor.generation; +package io.anuke.mindustry.maps.filters; 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.maps.filters.FilterOption.BlockOption; +import io.anuke.mindustry.maps.filters.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; +import static io.anuke.mindustry.maps.filters.FilterOption.floorsOnly; +import static io.anuke.mindustry.maps.filters.FilterOption.wallsOnly; public class TerrainFilter extends GenerateFilter{ float scl = 40, threshold = 0.9f, octaves = 3f, falloff = 0.5f, magnitude = 1f, circleScl = 2.1f; @@ -28,7 +28,7 @@ public class TerrainFilter extends GenerateFilter{ @Override public void apply(){ - float noise = noise(in.x, in.y, scl, magnitude, octaves, falloff) + Mathf.dst((float)in.x / in.editor.width(), (float)in.y / in.editor.height(), 0.5f, 0.5f) * circleScl; + float noise = noise(in.x, in.y, scl, magnitude, octaves, falloff) + Mathf.dst((float)in.x / in.width, (float)in.y / in.height, 0.5f, 0.5f) * circleScl; in.floor = floor; in.ore = Blocks.air; diff --git a/core/src/io/anuke/mindustry/maps/generators/MapGenerator.java b/core/src/io/anuke/mindustry/maps/generators/MapGenerator.java index 643f4c8b12..f8e0c1097e 100644 --- a/core/src/io/anuke/mindustry/maps/generators/MapGenerator.java +++ b/core/src/io/anuke/mindustry/maps/generators/MapGenerator.java @@ -1,22 +1,19 @@ package io.anuke.mindustry.maps.generators; -import io.anuke.arc.collection.Array; -import io.anuke.arc.math.Mathf; -import io.anuke.arc.math.geom.Point2; -import io.anuke.arc.util.Structs; -import io.anuke.arc.util.noise.Simplex; -import io.anuke.mindustry.content.Blocks; -import io.anuke.mindustry.io.MapIO; -import io.anuke.mindustry.maps.Map; -import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.type.Loadout; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.Tile; +import io.anuke.arc.collection.*; +import io.anuke.arc.math.*; +import io.anuke.arc.math.geom.*; +import io.anuke.arc.util.*; +import io.anuke.arc.util.noise.*; +import io.anuke.mindustry.content.*; +import io.anuke.mindustry.io.*; +import io.anuke.mindustry.maps.*; +import io.anuke.mindustry.type.*; +import io.anuke.mindustry.world.*; import io.anuke.mindustry.world.blocks.*; -import io.anuke.mindustry.world.blocks.storage.CoreBlock; -import io.anuke.mindustry.world.blocks.storage.StorageBlock; +import io.anuke.mindustry.world.blocks.storage.*; -import static io.anuke.mindustry.Vars.world; +import static io.anuke.mindustry.Vars.*; public class MapGenerator extends Generator{ private Map map; @@ -57,6 +54,14 @@ public class MapGenerator extends Generator{ return this; } + { + decor(new Decoration(Blocks.snow, Blocks.snowrock, 0.01), new Decoration(Blocks.ignarock, Blocks.pebbles, 0.03f)); + } + + public Map getMap(){ + return map; + } + @Override public void init(Loadout loadout){ this.loadout = loadout; @@ -73,13 +78,13 @@ public class MapGenerator extends Generator{ } } - MapIO.loadMap(map); + SaveIO.load(map.file); Array players = new Array<>(); Array enemies = new Array<>(); for(int x = 0; x < width; x++){ for(int y = 0; y < height; y++){ - if(tiles[x][y].block() instanceof CoreBlock){ + if(tiles[x][y].block() instanceof CoreBlock && tiles[x][y].getTeam() == defaultTeam){ players.add(new Point2(x, y)); tiles[x][y].setBlock(Blocks.air); } @@ -125,7 +130,9 @@ public class MapGenerator extends Generator{ 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)){ + }else if(tile.floor() == decor.floor && decor.wall.isOverlay() && Mathf.chance(decor.chance)){ + tile.setOverlay(decor.wall); + }else if(tile.floor() == decor.floor && decor.wall.isFloor() && !decor.wall.isOverlay() && Mathf.chance(decor.chance)){ tile.setFloor((Floor)decor.wall); } } diff --git a/core/src/io/anuke/mindustry/net/CrashSender.java b/core/src/io/anuke/mindustry/net/CrashSender.java index 11bb870905..f034c781dd 100644 --- a/core/src/io/anuke/mindustry/net/CrashSender.java +++ b/core/src/io/anuke/mindustry/net/CrashSender.java @@ -1,23 +1,21 @@ package io.anuke.mindustry.net; -import io.anuke.arc.Core; -import io.anuke.arc.collection.ObjectMap; -import io.anuke.arc.function.Consumer; -import io.anuke.arc.util.Log; -import io.anuke.arc.util.OS; -import io.anuke.arc.util.Strings; -import io.anuke.arc.util.io.PropertiesUtils; -import io.anuke.arc.util.serialization.JsonValue; -import io.anuke.arc.util.serialization.JsonValue.ValueType; -import io.anuke.arc.util.serialization.JsonWriter.OutputType; -import io.anuke.mindustry.Vars; -import io.anuke.mindustry.game.Version; +import io.anuke.arc.*; +import io.anuke.arc.collection.*; +import io.anuke.arc.function.*; +import io.anuke.arc.util.*; +import io.anuke.arc.util.io.*; +import io.anuke.arc.util.serialization.*; +import io.anuke.arc.util.serialization.JsonValue.*; +import io.anuke.arc.util.serialization.JsonWriter.*; +import io.anuke.mindustry.*; +import io.anuke.mindustry.game.*; import java.io.*; import java.nio.file.Files; -import java.nio.file.Paths; -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; +import java.nio.file.*; +import java.time.*; +import java.time.format.*; public class CrashSender{ @@ -32,7 +30,7 @@ public class CrashSender{ if(Version.number == 0){ try{ ObjectMap map = new ObjectMap<>(); - PropertiesUtils.load(map, new InputStreamReader(CrashSender.class.getResourceAsStream("version.properties"))); + PropertiesUtils.load(map, new InputStreamReader(CrashSender.class.getResourceAsStream("/version.properties"))); Version.type = map.get("type"); Version.number = Integer.parseInt(map.get("number")); @@ -45,10 +43,22 @@ public class CrashSender{ Version.build = Strings.canParseInt(map.get("build")) ? Integer.parseInt(map.get("build")) : -1; } }catch(Throwable ignored){ + ignored.printStackTrace(); Log.err("Failed to parse version."); } } + try{ + File file = new File(OS.getAppDataDirectoryString(Vars.appName), "crashes/crash-report-" + DateTimeFormatter.ofPattern("MM_dd_yyyy_HH_mm_ss").format(LocalDateTime.now()) + ".txt"); + new File(OS.getAppDataDirectoryString(Vars.appName)).mkdir(); + Files.write(file.toPath(), parseException(exception).getBytes()); + Files.createDirectories(Paths.get(OS.getAppDataDirectoryString(Vars.appName), "crashes")); + + writeListener.accept(file); + }catch(Throwable ignored){ + Log.err("Failed to save local crash report."); + } + try{ //check crash report setting if(!Core.settings.getBool("crashreport", true)){ @@ -63,17 +73,6 @@ public class CrashSender{ return; } - try{ - File file = new File(OS.getAppDataDirectoryString(Vars.appName), "crashes/crash-report-" + DateTimeFormatter.ofPattern("MM_dd_yyyy_HH_mm_ss").format(LocalDateTime.now()) + ".txt"); - new File(OS.getAppDataDirectoryString(Vars.appName)).mkdir(); - new BufferedOutputStream(new FileOutputStream(file), 2048).write(parseException(exception).getBytes()); - Files.createDirectories(Paths.get(OS.getAppDataDirectoryString(Vars.appName), "crashes")); - - writeListener.accept(file); - }catch(Throwable ignored){ - Log.err("Failed to save local crash report."); - } - boolean netActive = false, netServer = false; //attempt to close connections, if applicable @@ -104,7 +103,7 @@ public class CrashSender{ Log.info("Sending crash report."); //post to crash report URL - Net.http(Vars.crashReportURL, "POST", value.toJson(OutputType.json), r -> { + Core.net.httpPost(Vars.crashReportURL, value.toJson(OutputType.json), r -> { Log.info("Crash sent successfully."); sent[0] = true; System.exit(1); diff --git a/core/src/io/anuke/mindustry/net/Net.java b/core/src/io/anuke/mindustry/net/Net.java index 58fa2716aa..3943e8a4e2 100644 --- a/core/src/io/anuke/mindustry/net/Net.java +++ b/core/src/io/anuke/mindustry/net/Net.java @@ -1,11 +1,9 @@ package io.anuke.mindustry.net; import io.anuke.arc.Core; -import io.anuke.arc.Net.*; import io.anuke.arc.collection.*; import io.anuke.arc.function.BiConsumer; import io.anuke.arc.function.Consumer; -import io.anuke.arc.net.HttpRequestBuilder; import io.anuke.arc.util.*; import io.anuke.arc.util.pooling.Pools; import io.anuke.mindustry.core.Platform; @@ -29,17 +27,8 @@ public class Net{ private static ObjectMap, BiConsumer> serverListeners = new ObjectMap<>(); private static ClientProvider clientProvider; private static ServerProvider serverProvider; - private static IntMap streams = new IntMap<>(); - public static boolean hasClient(){ - return clientProvider != null; - } - - public static boolean hasServer(){ - return serverProvider != null; - } - /** Display a network error. Call on the graphics thread. */ public static void showError(Throwable e){ @@ -52,24 +41,30 @@ public class Net{ String error = t.getMessage() == null ? "" : t.getMessage().toLowerCase(); String type = t.getClass().toString().toLowerCase(); + boolean isError = false; if(e instanceof BufferUnderflowException || e instanceof BufferOverflowException){ error = Core.bundle.get("error.io"); }else if(error.equals("mismatch")){ error = Core.bundle.get("error.mismatch"); - }else if(error.contains("port out of range") || error.contains("invalid argument") || (error.contains("invalid") && error.contains("address"))){ + }else if(error.contains("port out of range") || error.contains("invalid argument") || (error.contains("invalid") && error.contains("address")) || Strings.parseException(e, true).contains("address associated")){ error = Core.bundle.get("error.invalidaddress"); }else if(error.contains("connection refused") || error.contains("route to host") || type.contains("unknownhost")){ error = Core.bundle.get("error.unreachable"); }else if(type.contains("timeout")){ error = Core.bundle.get("error.timedout"); - }else if(error.equals("alreadyconnected")){ + }else if(error.equals("alreadyconnected") || error.contains("connection is closed")){ error = Core.bundle.get("error.alreadyconnected"); }else if(!error.isEmpty()){ error = Core.bundle.get("error.any") + "\n" + Strings.parseException(e, true); + isError = true; } - ui.showText("", Core.bundle.format("connectfail", error)); + if(isError){ + ui.showError(Core.bundle.format("connectfail", error)); + }else{ + ui.showText("", Core.bundle.format("connectfail", error)); + } ui.loadfrag.hide(); if(Net.client()){ @@ -333,31 +328,6 @@ public class Net{ active = false; } - public static void http(String url, String method, Consumer listener, Consumer failure){ - http(url, method, null, listener, failure); - } - - public static void http(String url, String method, String body, Consumer listener, Consumer failure){ - HttpRequest req = new HttpRequestBuilder().newRequest() - .method(method).url(url).content(body).build(); - - Core.net.sendHttpRequest(req, new HttpResponseListener(){ - @Override - public void handleHttpResponse(HttpResponse httpResponse){ - listener.accept(httpResponse.getResultAsString()); - } - - @Override - public void failed(Throwable t){ - failure.accept(t); - } - - @Override - public void cancelled(){ - } - }); - } - public enum SendMode{ tcp, udp } diff --git a/core/src/io/anuke/mindustry/type/ContentType.java b/core/src/io/anuke/mindustry/type/ContentType.java index 125ccc8221..31ddcf35d2 100644 --- a/core/src/io/anuke/mindustry/type/ContentType.java +++ b/core/src/io/anuke/mindustry/type/ContentType.java @@ -12,5 +12,6 @@ public enum ContentType{ weather, effect, zone, - loadout + loadout, + typeid } diff --git a/core/src/io/anuke/mindustry/type/Item.java b/core/src/io/anuke/mindustry/type/Item.java index 2993908713..b3ae589254 100644 --- a/core/src/io/anuke/mindustry/type/Item.java +++ b/core/src/io/anuke/mindustry/type/Item.java @@ -69,7 +69,7 @@ public class Item extends UnlockableContent implements Comparable{ @Override public TextureRegion getContentIcon(){ - return icon(Icon.xlarge); + return icon(Icon.large); } @Override @@ -91,7 +91,8 @@ public class Item extends UnlockableContent implements Comparable{ small(8 * 2), medium(8 * 3), large(8 * 4), - xlarge(8 * 5); + xlarge(8 * 5), + xxlarge(8 * 6); public final int size; diff --git a/core/src/io/anuke/mindustry/type/Loadout.java b/core/src/io/anuke/mindustry/type/Loadout.java index aebdaf03bc..05339c3d1b 100644 --- a/core/src/io/anuke/mindustry/type/Loadout.java +++ b/core/src/io/anuke/mindustry/type/Loadout.java @@ -1,18 +1,16 @@ 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.game.Content; +import io.anuke.arc.collection.*; +import io.anuke.mindustry.content.*; +import io.anuke.mindustry.game.*; import io.anuke.mindustry.world.*; -import io.anuke.mindustry.world.blocks.storage.CoreBlock; +import io.anuke.mindustry.world.blocks.storage.*; -import static io.anuke.mindustry.Vars.defaultTeam; -import static io.anuke.mindustry.Vars.world; +import static io.anuke.mindustry.Vars.*; public class Loadout extends Content{ - private final static Array outArray = new Array<>(); - private final static IntMap entries = new IntMap(){{ + private final Array outArray = new Array<>(); + private final IntMap entries = new IntMap(){{ put('>', new BlockEntry(Blocks.conveyor, 0)); put('^', new BlockEntry(Blocks.conveyor, 1)); put('<', new BlockEntry(Blocks.conveyor, 2)); @@ -70,6 +68,8 @@ public class Loadout extends Content{ int rx = Pos.x(entry.key); int ry = Pos.y(entry.key); Tile tile = world.tile(x + rx, y + ry); + if(tile == null) continue; + world.setBlock(tile, entry.value.block, defaultTeam); tile.rotation((byte)entry.value.rotation); if(entry.value.ore != null){ diff --git a/core/src/io/anuke/mindustry/type/UnitType.java b/core/src/io/anuke/mindustry/type/UnitType.java index d187380fb0..bfe6042e23 100644 --- a/core/src/io/anuke/mindustry/type/UnitType.java +++ b/core/src/io/anuke/mindustry/type/UnitType.java @@ -6,14 +6,14 @@ import io.anuke.arc.function.Supplier; import io.anuke.arc.graphics.g2d.TextureRegion; import io.anuke.arc.scene.ui.layout.Table; import io.anuke.mindustry.content.Items; -import io.anuke.mindustry.entities.traits.TypeTrait; import io.anuke.mindustry.entities.type.BaseUnit; -import io.anuke.mindustry.game.Team; -import io.anuke.mindustry.game.UnlockableContent; +import io.anuke.mindustry.game.*; import io.anuke.mindustry.ui.ContentDisplay; public class UnitType extends UnlockableContent{ - protected final Supplier constructor; + public final TypeID typeID; + public final Supplier constructor; + public float health = 60; public float hitsize = 7f; public float hitsizeTile = 4f; @@ -28,7 +28,7 @@ public class UnitType extends UnlockableContent{ public boolean rotateWeapon = false; public float drag = 0.1f; public float maxVelocity = 5f; - public float retreatPercent = 0.2f; + public float retreatPercent = 0.6f; public int itemCapacity = 30; public ObjectSet toMine = ObjectSet.with(Items.lead, Items.copper); public float buildPower = 0.3f, minePower = 0.7f; @@ -42,8 +42,7 @@ public class UnitType extends UnlockableContent{ super(name); this.constructor = mainConstructor; this.description = Core.bundle.getOrNull("unit." + name + ".description"); - - TypeTrait.registerType(type, mainConstructor); + this.typeID = new TypeID(name, mainConstructor); } @Override @@ -66,11 +65,8 @@ public class UnitType extends UnlockableContent{ weapon.load(); iconRegion = Core.atlas.find("unit-icon-" + name, Core.atlas.find(name)); region = Core.atlas.find(name); - - if(!isFlying){ - legRegion = Core.atlas.find(name + "-leg"); - baseRegion = Core.atlas.find(name + "-base"); - } + legRegion = Core.atlas.find(name + "-leg"); + baseRegion = Core.atlas.find(name + "-base"); } @Override diff --git a/core/src/io/anuke/mindustry/type/Zone.java b/core/src/io/anuke/mindustry/type/Zone.java index 74ec3d9183..069f8eb9c0 100644 --- a/core/src/io/anuke/mindustry/type/Zone.java +++ b/core/src/io/anuke/mindustry/type/Zone.java @@ -1,22 +1,18 @@ package io.anuke.mindustry.type; -import io.anuke.arc.Core; -import io.anuke.arc.Events; -import io.anuke.arc.collection.Array; -import io.anuke.arc.function.Consumer; -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.Structs; -import io.anuke.mindustry.content.Loadouts; -import io.anuke.mindustry.game.EventType.ZoneConfigureCompleteEvent; -import io.anuke.mindustry.game.EventType.ZoneRequireCompleteEvent; -import io.anuke.mindustry.game.Rules; -import io.anuke.mindustry.game.UnlockableContent; -import io.anuke.mindustry.maps.generators.Generator; -import io.anuke.mindustry.world.Block; +import io.anuke.arc.*; +import io.anuke.arc.collection.*; +import io.anuke.arc.function.*; +import io.anuke.arc.graphics.g2d.*; +import io.anuke.arc.scene.ui.layout.*; +import io.anuke.arc.util.*; +import io.anuke.mindustry.content.*; +import io.anuke.mindustry.game.EventType.*; +import io.anuke.mindustry.game.*; +import io.anuke.mindustry.maps.generators.*; +import io.anuke.mindustry.world.*; -import java.util.Arrays; +import java.util.*; import static io.anuke.mindustry.Vars.*; @@ -25,7 +21,7 @@ public class Zone extends UnlockableContent{ public Block[] blockRequirements = {}; public ZoneRequirement[] zoneRequirements = {}; public Item[] resources = {}; - public Supplier rules = Rules::new; + public Consumer rules = rules -> {}; public boolean alwaysUnlocked; public int conditionWave = Integer.MAX_VALUE; public int configureWave = 15; @@ -43,6 +39,16 @@ public class Zone extends UnlockableContent{ this.generator = generator; } + public Rules getRules(){ + if(generator instanceof MapGenerator){ + return ((MapGenerator)generator).getMap().rules(); + }else{ + Rules rules = new Rules(); + this.rules.accept(rules); + return rules; + } + } + public boolean isBossWave(int wave){ return wave % configureWave == 0 && wave > 0; } @@ -122,7 +128,8 @@ public class Zone extends UnlockableContent{ /** Whether this zone has met its condition; if true, the player can leave. */ public boolean metCondition(){ - return state.wave >= conditionWave; + //players can't leave in attack mode. + return state.wave >= conditionWave && !state.rules.attackMode; } public boolean canConfigure(){ diff --git a/core/src/io/anuke/mindustry/ui/BorderImage.java b/core/src/io/anuke/mindustry/ui/BorderImage.java index 6c7a8e54d9..a1191e2414 100644 --- a/core/src/io/anuke/mindustry/ui/BorderImage.java +++ b/core/src/io/anuke/mindustry/ui/BorderImage.java @@ -7,7 +7,7 @@ import io.anuke.arc.scene.ui.layout.Unit; import io.anuke.mindustry.graphics.Pal; public class BorderImage extends Image{ - private float thickness = 3f; + private float thickness = 4f; public BorderImage(){ @@ -34,7 +34,7 @@ public class BorderImage extends Image{ float scaleX = getScaleX(); float scaleY = getScaleY(); - Draw.color(Pal.accent); + Draw.color(Pal.gray); Draw.alpha(parentAlpha); Lines.stroke(Unit.dp.scl(thickness)); Lines.rect(x + imageX, y + imageY, imageWidth * scaleX, imageHeight * scaleY); diff --git a/core/src/io/anuke/mindustry/ui/ContentDisplay.java b/core/src/io/anuke/mindustry/ui/ContentDisplay.java index f00506202d..6c293d1686 100644 --- a/core/src/io/anuke/mindustry/ui/ContentDisplay.java +++ b/core/src/io/anuke/mindustry/ui/ContentDisplay.java @@ -25,7 +25,7 @@ public class ContentDisplay{ table.row(); - table.addImage("white").height(3).color(Color.LIGHT_GRAY).pad(8).padLeft(0).padRight(0).fillX(); + table.addImage("whiteui").height(3).color(Color.LIGHT_GRAY).pad(8).padLeft(0).padRight(0).fillX(); table.row(); @@ -33,7 +33,7 @@ public class ContentDisplay{ table.add(block.description).padLeft(5).padRight(5).width(400f).wrap().fillX(); table.row(); - table.addImage("white").height(3).color(Color.LIGHT_GRAY).pad(8).padLeft(0).padRight(0).fillX(); + table.addImage("whiteui").height(3).color(Color.LIGHT_GRAY).pad(8).padLeft(0).padRight(0).fillX(); table.row(); } @@ -73,7 +73,7 @@ public class ContentDisplay{ table.row(); - table.addImage("white").height(3).color(Color.LIGHT_GRAY).pad(15).padLeft(0).padRight(0).fillX(); + table.addImage("whiteui").height(3).color(Color.LIGHT_GRAY).pad(15).padLeft(0).padRight(0).fillX(); table.row(); @@ -81,7 +81,7 @@ public class ContentDisplay{ table.add(item.description).padLeft(5).padRight(5).width(400f).wrap().fillX(); table.row(); - table.addImage("white").height(3).color(Color.LIGHT_GRAY).pad(15).padLeft(0).padRight(0).fillX(); + table.addImage("whiteui").height(3).color(Color.LIGHT_GRAY).pad(15).padLeft(0).padRight(0).fillX(); table.row(); } @@ -104,7 +104,7 @@ public class ContentDisplay{ table.row(); - table.addImage("white").height(3).color(Color.LIGHT_GRAY).pad(15).padLeft(0).padRight(0).fillX(); + table.addImage("whiteui").height(3).color(Color.LIGHT_GRAY).pad(15).padLeft(0).padRight(0).fillX(); table.row(); @@ -112,7 +112,7 @@ public class ContentDisplay{ table.add(liquid.description).padLeft(5).padRight(5).width(400f).wrap().fillX(); table.row(); - table.addImage("white").height(3).color(Color.LIGHT_GRAY).pad(15).padLeft(0).padRight(0).fillX(); + table.addImage("whiteui").height(3).color(Color.LIGHT_GRAY).pad(15).padLeft(0).padRight(0).fillX(); table.row(); } @@ -139,7 +139,7 @@ public class ContentDisplay{ table.row(); - table.addImage("white").height(3).color(Color.LIGHT_GRAY).pad(15).padLeft(0).padRight(0).fillX(); + table.addImage("whiteui").height(3).color(Color.LIGHT_GRAY).pad(15).padLeft(0).padRight(0).fillX(); table.row(); @@ -147,7 +147,7 @@ public class ContentDisplay{ table.add(mech.description).padLeft(5).padRight(5).width(400f).wrap().fillX(); table.row(); - table.addImage("white").height(3).color(Color.LIGHT_GRAY).pad(15).padLeft(0).padRight(0).fillX(); + table.addImage("whiteui").height(3).color(Color.LIGHT_GRAY).pad(15).padLeft(0).padRight(0).fillX(); table.row(); } @@ -186,7 +186,7 @@ public class ContentDisplay{ table.row(); - table.addImage("white").height(3).color(Color.LIGHT_GRAY).pad(15).padLeft(0).padRight(0).fillX(); + table.addImage("whiteui").height(3).color(Color.LIGHT_GRAY).pad(15).padLeft(0).padRight(0).fillX(); table.row(); @@ -194,7 +194,7 @@ public class ContentDisplay{ table.add(unit.description).padLeft(5).padRight(5).width(400f).wrap().fillX(); table.row(); - table.addImage("white").height(3).color(Color.LIGHT_GRAY).pad(15).padLeft(0).padRight(0).fillX(); + table.addImage("whiteui").height(3).color(Color.LIGHT_GRAY).pad(15).padLeft(0).padRight(0).fillX(); table.row(); } diff --git a/core/src/io/anuke/mindustry/ui/IntFormat.java b/core/src/io/anuke/mindustry/ui/IntFormat.java index cdf1e529ad..22d50ab495 100644 --- a/core/src/io/anuke/mindustry/ui/IntFormat.java +++ b/core/src/io/anuke/mindustry/ui/IntFormat.java @@ -2,6 +2,7 @@ package io.anuke.mindustry.ui; import io.anuke.arc.Core; +import io.anuke.arc.function.Function; /** * A low-garbage way to format bundle strings. @@ -10,15 +11,21 @@ public class IntFormat{ private final StringBuilder builder = new StringBuilder(); private final String text; private int lastValue = Integer.MIN_VALUE; + private Function converter = String::valueOf; public IntFormat(String text){ this.text = text; } + public IntFormat(String text, Function converter){ + this.text = text; + this.converter = converter; + } + public CharSequence get(int value){ if(lastValue != value){ builder.setLength(0); - builder.append(Core.bundle.format(text, value)); + builder.append(Core.bundle.format(text, converter.get(value))); } lastValue = value; return builder; diff --git a/core/src/io/anuke/mindustry/ui/ItemsDisplay.java b/core/src/io/anuke/mindustry/ui/ItemsDisplay.java index 684cc07aa1..97208b54ab 100644 --- a/core/src/io/anuke/mindustry/ui/ItemsDisplay.java +++ b/core/src/io/anuke/mindustry/ui/ItemsDisplay.java @@ -26,7 +26,7 @@ public class ItemsDisplay extends Table{ top().left(); margin(0); - table("flat", t -> { + table("button", t -> { t.margin(10).marginLeft(15).marginTop(15f); t.add("$launcheditems").colspan(3).left().padBottom(5); t.row(); diff --git a/core/src/io/anuke/mindustry/ui/Links.java b/core/src/io/anuke/mindustry/ui/Links.java index 41a1196d70..a0c0cae0f9 100644 --- a/core/src/io/anuke/mindustry/ui/Links.java +++ b/core/src/io/anuke/mindustry/ui/Links.java @@ -2,19 +2,22 @@ package io.anuke.mindustry.ui; import io.anuke.arc.Core; import io.anuke.arc.graphics.Color; +import io.anuke.mindustry.graphics.Pal; public class Links{ private static LinkEntry[] links; private static void createLinks(){ links = new LinkEntry[]{ - new LinkEntry("discord", "https://discord.gg/mindustry", Color.valueOf("7289da")), - new LinkEntry("trello", "https://trello.com/b/aE2tcUwF", Color.valueOf("026aa7")), - new LinkEntry("wiki", "https://mindustrygame.github.io/wiki/", Color.valueOf("0f142f")), - new LinkEntry("itch.io", "https://anuke.itch.io/mindustry", Color.valueOf("fa5c5c")), - new LinkEntry("google-play", "https://play.google.com/store/apps/details?id=io.anuke.mindustry", Color.valueOf("689f38")), - new LinkEntry("github", "https://github.com/Anuken/Mindustry/", Color.valueOf("24292e")), - new LinkEntry("dev-builds", "https://jenkins.hellomouse.net/job/mindustry/", Color.valueOf("fafbfc")) + new LinkEntry("discord", "https://discord.gg/mindustry", Color.valueOf("7289da")), + new LinkEntry("changelog", "https://github.com/Anuken/Mindustry/releases", Pal.accent.cpy()), + new LinkEntry("trello", "https://trello.com/b/aE2tcUwF", Color.valueOf("026aa7")), + new LinkEntry("wiki", "https://mindustrygame.github.io/wiki/", Color.valueOf("0f142f")), + new LinkEntry("itch.io", "https://anuke.itch.io/mindustry", Color.valueOf("fa5c5c")), + new LinkEntry("google-play", "https://play.google.com/store/apps/details?id=io.anuke.mindustry", Color.valueOf("689f38")), + new LinkEntry("github", "https://github.com/Anuken/Mindustry/", Color.valueOf("24292e")), + new LinkEntry("dev-builds", "https://jenkins.hellomouse.net/job/mindustry/", Color.valueOf("fafbfc")) + }; } diff --git a/core/src/io/anuke/mindustry/ui/MenuButton.java b/core/src/io/anuke/mindustry/ui/MenuButton.java deleted file mode 100644 index 80f577f4cf..0000000000 --- a/core/src/io/anuke/mindustry/ui/MenuButton.java +++ /dev/null @@ -1,31 +0,0 @@ -package io.anuke.mindustry.ui; - -import io.anuke.arc.graphics.Color; -import io.anuke.arc.scene.ui.TextButton; -import io.anuke.arc.util.Align; - -public class MenuButton extends TextButton{ - - public MenuButton(String icon, String text, Runnable clicked){ - this(icon, text, null, clicked); - } - - public MenuButton(String icon, String text, String description, Runnable clicked){ - super("default"); - - clicked(clicked); - clearChildren(); - - margin(0); - - table(t -> { - t.addImage(icon).size(14 * 3).padLeft(6); - - t.add(text).wrap().growX().get().setAlignment(Align.center, Align.left); - if(description != null){ - t.row(); - t.add(description).color(Color.LIGHT_GRAY); - } - }).padLeft(5).growX(); - } -} diff --git a/core/src/io/anuke/mindustry/ui/Minimap.java b/core/src/io/anuke/mindustry/ui/Minimap.java index e39e128e3e..8b222834fa 100644 --- a/core/src/io/anuke/mindustry/ui/Minimap.java +++ b/core/src/io/anuke/mindustry/ui/Minimap.java @@ -5,26 +5,25 @@ import io.anuke.arc.graphics.g2d.Draw; import io.anuke.arc.input.KeyCode; import io.anuke.arc.scene.Element; import io.anuke.arc.scene.event.*; -import io.anuke.arc.scene.ui.layout.Container; -import io.anuke.arc.scene.ui.layout.Unit; +import io.anuke.arc.scene.ui.layout.*; import static io.anuke.mindustry.Vars.*; -public class Minimap extends Container{ +public class Minimap extends Table{ public Minimap(){ background("pane"); float margin = 5f; touchable(Touchable.enabled); - addChild(new Element(){ + add(new Element(){ { setSize(Unit.dp.scl(140f)); } @Override public void act(float delta){ - setPosition(margin, margin); + setPosition(Unit.dp.scl(margin), Unit.dp.scl(margin)); super.act(delta); } @@ -39,9 +38,8 @@ public class Minimap extends Container{ renderer.minimap.drawEntities(x, y, width, height); } } - }); + }).size(140f); - size(140f); margin(margin); addListener(new InputListener(){ diff --git a/core/src/io/anuke/mindustry/ui/dialogs/AboutDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/AboutDialog.java index 0ba3aaddd4..bac51b97bf 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/AboutDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/AboutDialog.java @@ -20,7 +20,7 @@ public class AboutDialog extends FloatingDialog{ super("$about.button"); shown(() -> { - contributors = Array.with(Core.files.internal("contributors").readString().split("\n")); + contributors = Array.with(Core.files.internal("contributors").readString("UTF-8").split("\n")); Core.app.post(this::setup); }); @@ -46,14 +46,14 @@ public class AboutDialog extends FloatingDialog{ Table table = new Table("underline"); table.margin(0); table.table(img -> { - img.addImage("white").height(h - 5).width(40f).color(link.color); + img.addImage("whiteui").height(h - 5).width(40f).color(link.color); img.row(); - img.addImage("white").height(5).width(40f).color(link.color.cpy().mul(0.8f, 0.8f, 0.8f, 1f)); + img.addImage("whiteui").height(5).width(40f).color(link.color.cpy().mul(0.8f, 0.8f, 0.8f, 1f)); }).expandY(); table.table(i -> { i.background("button-edge-3"); - i.addImage("icon-" + link.name).size(14 * 3f); + i.addImage("icon-" + link.name).size(iconsize); }).size(h - 5, h); table.table(inset -> { @@ -62,10 +62,10 @@ public class AboutDialog extends FloatingDialog{ inset.labelWrap(link.description).width(w - 100f).color(Color.LIGHT_GRAY).growX(); }).padLeft(8); - table.addImageButton("icon-link", 14 * 3, () -> { + table.addImageButton("icon-link", iconsize, () -> { if(!Core.net.openURI(link.link)){ ui.showError("$linkfail"); - Core.app.getClipboard().setContents(link.link); + Core.app.setClipboardText(link.link); } }).size(h - 5, h); @@ -80,10 +80,6 @@ public class AboutDialog extends FloatingDialog{ buttons.addButton("$credits", this::showCredits).size(200f, 64f); - if(!ios && !OS.isMac){ - buttons.addButton("$changelog.title", ui.changelog::show).size(200f, 64f); - } - if(Core.graphics.isPortrait()){ for(Cell cell : buttons.getCells()){ cell.width(140f); @@ -98,7 +94,7 @@ public class AboutDialog extends FloatingDialog{ dialog.cont.add("$credits.text"); dialog.cont.row(); if(!contributors.isEmpty()){ - dialog.cont.addImage("blank").color(Pal.accent).fillX().height(3f).pad(3f); + dialog.cont.addImage("whiteui").color(Pal.accent).fillX().height(3f).pad(3f); dialog.cont.row(); dialog.cont.add("$contributors"); dialog.cont.row(); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/AdminsDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/AdminsDialog.java index 2c83b7fbcb..2462ec9fe4 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/AdminsDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/AdminsDialog.java @@ -37,7 +37,7 @@ public class AdminsDialog extends FloatingDialog{ res.labelWrap("[LIGHT_GRAY]" + info.lastName).width(w - h - 24f); res.add().growX(); - res.addImageButton("icon-cancel", 14 * 3, () -> { + res.addImageButton("icon-cancel", iconsize, () -> { ui.showConfirm("$confirm", "$confirmunadmin", () -> { netServer.admins.unAdminPlayer(info.id); playerGroup.all().each(player -> { diff --git a/core/src/io/anuke/mindustry/ui/dialogs/BansDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/BansDialog.java index be60408759..9caad501c1 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/BansDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/BansDialog.java @@ -4,8 +4,7 @@ import io.anuke.arc.scene.ui.ScrollPane; import io.anuke.arc.scene.ui.layout.Table; import io.anuke.mindustry.net.Administration.PlayerInfo; -import static io.anuke.mindustry.Vars.netServer; -import static io.anuke.mindustry.Vars.ui; +import static io.anuke.mindustry.Vars.*; public class BansDialog extends FloatingDialog{ @@ -39,7 +38,7 @@ public class BansDialog extends FloatingDialog{ res.labelWrap("IP: [LIGHT_GRAY]" + info.lastIP + "\n[]Name: [LIGHT_GRAY]" + info.lastName).width(w - h - 24f); res.add().growX(); - res.addImageButton("icon-cancel", 14 * 3, () -> { + res.addImageButton("icon-cancel", iconsize, () -> { ui.showConfirm("$confirm", "$confirmunban", () -> { netServer.admins.unbanPlayerID(info.id); setup(); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/ChangelogDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/ChangelogDialog.java deleted file mode 100644 index 9bea180562..0000000000 --- a/core/src/io/anuke/mindustry/ui/dialogs/ChangelogDialog.java +++ /dev/null @@ -1,89 +0,0 @@ -package io.anuke.mindustry.ui.dialogs; - -import io.anuke.arc.Core; -import io.anuke.arc.collection.Array; -import io.anuke.arc.scene.ui.ScrollPane; -import io.anuke.arc.scene.ui.layout.Table; -import io.anuke.arc.util.Log; -import io.anuke.arc.util.OS; -import io.anuke.mindustry.Vars; -import io.anuke.mindustry.game.Version; -import io.anuke.mindustry.io.Changelogs; -import io.anuke.mindustry.io.Changelogs.VersionInfo; - -import static io.anuke.mindustry.Vars.ios; - -public class ChangelogDialog extends FloatingDialog{ - private final float vw = 600; - private Array versions; - - public ChangelogDialog(){ - super("$changelog.title"); - - addCloseButton(); - - cont.add("$changelog.loading"); - - shown(() -> { - if(!ios && !OS.isMac){ - Changelogs.getChangelog(result -> { - versions = result; - Core.app.post(this::setup); - }, t -> { - Log.err(t); - Core.app.post(this::setup); - }); - } - }); - } - - void setup(){ - Table table = new Table(); - ScrollPane pane = new ScrollPane(table); - - cont.clear(); - cont.add(pane).grow(); - - if(versions == null){ - table.add("$changelog.error"); - if(Vars.android){ - table.row(); - table.add("$changelog.error.android").padTop(8); - } - - if(ios){ - table.row(); - table.add("$changelog.error.ios").padTop(8); - } - }else{ - for(VersionInfo info : versions){ - String desc = info.description; - - desc = desc.replace("Android", "Mobile"); - - Table in = new Table("underline"); - in.top().left().margin(10); - - in.add("[accent]" + info.name + "[LIGHT_GRAY] | " + info.date); - if(info.build == Version.build){ - in.row(); - in.add("$changelog.current"); - }else if(info == versions.first()){ - in.row(); - in.add("$changelog.latest"); - } - in.row(); - in.labelWrap("[lightgray]" + desc).width(vw - 20).padTop(12); - - table.add(in).width(vw).pad(8).row(); - } - - int lastid = Core.settings.getInt("lastBuild"); - if(lastid != 0 && versions.peek().build > lastid){ - Core.settings.put("lastBuild", versions.peek().build); - Core.settings.save(); - show(); - } - } - } -} diff --git a/core/src/io/anuke/mindustry/ui/dialogs/ColorPickDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/ColorPickDialog.java index a737782b8e..3ea7f3d3d4 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/ColorPickDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/ColorPickDialog.java @@ -25,7 +25,7 @@ public class ColorPickDialog extends Dialog{ for(int i = 0; i < playerColors.length; i++){ Color color = playerColors[i]; - ImageButton button = table.addImageButton("white", "clear-toggle", 34, () -> { + ImageButton button = table.addImageButton("whiteui", "clear-toggle", 34, () -> { cons.accept(color); hide(); }).size(48).get(); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/ControlsDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/ControlsDialog.java index aad28dc08e..c63c845248 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/ControlsDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/ControlsDialog.java @@ -2,9 +2,9 @@ package io.anuke.mindustry.ui.dialogs; import io.anuke.arc.Core; import io.anuke.arc.input.KeyCode; -import io.anuke.arc.scene.ui.Image; -import io.anuke.arc.scene.ui.KeybindDialog; +import io.anuke.arc.scene.ui.*; import io.anuke.arc.util.Align; +import io.anuke.mindustry.Vars; import io.anuke.mindustry.graphics.Pal; public class ControlsDialog extends KeybindDialog{ @@ -15,8 +15,13 @@ public class ControlsDialog extends KeybindDialog{ setFillParent(true); title.setAlignment(Align.center); titleTable.row(); - titleTable.add(new Image("white")) + titleTable.add(new Image("whiteui")) .growX().height(3f).pad(4f).get().setColor(Pal.accent); + if(Vars.mobile){ + cont.row(); + cont.add("$keybinds.mobile") + .center().growX().wrap().get().setAlignment(Align.center); + } } @Override diff --git a/core/src/io/anuke/mindustry/ui/dialogs/CustomGameDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/CustomGameDialog.java index 0aabd0272b..dade138dc8 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/CustomGameDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/CustomGameDialog.java @@ -1,19 +1,19 @@ package io.anuke.mindustry.ui.dialogs; -import io.anuke.arc.Core; -import io.anuke.arc.graphics.g2d.TextureRegion; -import io.anuke.arc.scene.ui.ImageButton; -import io.anuke.arc.scene.ui.ScrollPane; -import io.anuke.arc.scene.ui.layout.Table; -import io.anuke.arc.util.Align; -import io.anuke.arc.util.Scaling; -import io.anuke.mindustry.maps.Map; -import io.anuke.mindustry.ui.BorderImage; +import io.anuke.arc.*; +import io.anuke.arc.graphics.g2d.*; +import io.anuke.arc.math.*; +import io.anuke.arc.scene.ui.*; +import io.anuke.arc.scene.ui.layout.*; +import io.anuke.arc.util.*; +import io.anuke.mindustry.game.*; +import io.anuke.mindustry.graphics.*; +import io.anuke.mindustry.maps.*; +import io.anuke.mindustry.ui.*; import static io.anuke.mindustry.Vars.world; -public class -CustomGameDialog extends FloatingDialog{ +public class CustomGameDialog extends FloatingDialog{ private MapPlayDialog dialog = new MapPlayDialog(); public CustomGameDialog(){ @@ -33,10 +33,11 @@ CustomGameDialog extends FloatingDialog{ Table maps = new Table(); maps.marginRight(14); + maps.marginBottom(55f); ScrollPane pane = new ScrollPane(maps); pane.setFadeScrollBars(false); - int maxwidth = (Core.graphics.isPortrait() ? 2 : 4); + int maxwidth = Mathf.clamp((int)(Core.graphics.getWidth() / Unit.dp.scl(200)), 1, 8); float images = 146f; int i = 0; @@ -49,12 +50,27 @@ CustomGameDialog extends FloatingDialog{ ImageButton image = new ImageButton(new TextureRegion(map.texture), "clear"); image.margin(5); - image.getImageCell().size(images); image.top(); + + Image img = image.getImage(); + img.remove(); + image.row(); - image.add("[accent]" + map.name()).pad(3f).growX().wrap().get().setAlignment(Align.center, Align.center); + image.table(t -> { + t.left(); + for(Gamemode mode : Gamemode.all){ + if(mode.valid(map) && Core.atlas.has("icon-mode-" + mode.name())){ + t.addImage("icon-mode-" + mode.name()).size(16f).pad(4f); + } + } + }).left(); image.row(); - image.label((() -> Core.bundle.format("level.highscore", map.getHightScore()))).pad(3f); + image.add(map.name()).pad(1f).growX().wrap().left().get().setEllipsis(true); + image.row(); + image.addImage("whiteui", Pal.gray).growX().pad(3).height(4f); + image.row(); + image.add(img).size(images); + BorderImage border = new BorderImage(map.texture, 3f); border.setScaling(Scaling.fit); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/CustomRulesDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/CustomRulesDialog.java index 6233e762f2..ea0cb7940d 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/CustomRulesDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/CustomRulesDialog.java @@ -4,9 +4,13 @@ import io.anuke.arc.function.*; import io.anuke.arc.graphics.Color; import io.anuke.arc.scene.ui.layout.Table; import io.anuke.arc.util.Strings; +import io.anuke.mindustry.content.Blocks; +import io.anuke.mindustry.content.Items; import io.anuke.mindustry.core.Platform; import io.anuke.mindustry.game.Rules; import io.anuke.mindustry.graphics.Pal; +import io.anuke.mindustry.type.ItemStack; +import io.anuke.mindustry.type.ItemType; import static io.anuke.mindustry.Vars.tilesize; @@ -14,10 +18,12 @@ public class CustomRulesDialog extends FloatingDialog{ private Table main; private Rules rules; private Supplier resetter; + private LoadoutDialog loadoutDialog; public CustomRulesDialog(){ super("$mode.custom"); + loadoutDialog = new LoadoutDialog(); setFillParent(true); shown(this::setup); addCloseButton(); @@ -48,8 +54,9 @@ public class CustomRulesDialog extends FloatingDialog{ number("$rules.dropzoneradius", false, f -> rules.dropZoneRadius = f * tilesize, () -> rules.dropZoneRadius / tilesize, () -> true); title("$rules.title.respawns"); - check("$rules.limitedRespawns", b -> rules.limitedRespawns = b, () -> rules.limitedRespawns); - number("$rules.respawns", true, f -> rules.respawns = (int)f, () -> rules.respawns, () -> rules.limitedRespawns); + //limited respawns don't work on PvP, commented out until they're fixed + //check("$rules.limitedRespawns", b -> rules.limitedRespawns = b, () -> rules.limitedRespawns); + //number("$rules.respawns", true, f -> rules.respawns = (int)f, () -> rules.respawns, () -> rules.limitedRespawns); number("$rules.respawntime", f -> rules.respawnTime = f * 60f, () -> rules.respawnTime / 60f); title("$rules.title.resourcesbuilding"); @@ -57,6 +64,19 @@ public class CustomRulesDialog extends FloatingDialog{ number("$rules.buildcostmultiplier", false, f -> rules.buildCostMultiplier = f, () -> rules.buildCostMultiplier, () -> !rules.infiniteResources); number("$rules.buildspeedmultiplier", f -> rules.buildSpeedMultiplier = f, () -> rules.buildSpeedMultiplier); + main.addButton("$configure", + () -> loadoutDialog.show( + Blocks.coreShard.itemCapacity, + () -> rules.loadout, + () -> { + rules.loadout.clear(); + rules.loadout.add(new ItemStack(Items.copper, 200)); + }, + () -> {}, () -> {}, + item -> item.type == ItemType.material + )).left().width(300f); + main.row(); + title("$rules.title.player"); number("$rules.playerdamagemultiplier", f -> rules.playerDamageMultiplier = f, () -> rules.playerDamageMultiplier); number("$rules.playerhealthmultiplier", f -> rules.playerHealthMultiplier = f, () -> rules.playerHealthMultiplier); @@ -68,6 +88,8 @@ public class CustomRulesDialog extends FloatingDialog{ number("$rules.unitdamagemultiplier", f -> rules.unitDamageMultiplier = f, () -> rules.unitDamageMultiplier); title("$rules.title.enemy"); + check("$rules.attack", b -> rules.attackMode = b, () -> rules.attackMode); + check("$rules.enemyCheat", b -> rules.enemyCheat = b, () -> rules.enemyCheat); number("$rules.enemycorebuildradius", f -> rules.enemyCoreBuildRadius = f * tilesize, () -> Math.min(rules.enemyCoreBuildRadius / tilesize, 200)); } @@ -93,7 +115,7 @@ public class CustomRulesDialog extends FloatingDialog{ } void check(String text, BooleanConsumer cons, BooleanProvider prov, BooleanProvider condition){ - main.addCheck(text, cons).checked(prov.get()).update(a -> a.setDisabled(!condition.get())).padRight(100f); + main.addCheck(text, cons).checked(prov.get()).update(a -> a.setDisabled(!condition.get())).padRight(100f).get().left(); main.row(); } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/DatabaseDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/DatabaseDialog.java index e4565db51b..99b05d1ea4 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/DatabaseDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/DatabaseDialog.java @@ -2,9 +2,12 @@ package io.anuke.mindustry.ui.dialogs; import io.anuke.arc.Core; import io.anuke.arc.collection.Array; +import io.anuke.arc.graphics.Color; +import io.anuke.arc.scene.event.ClickListener; import io.anuke.arc.scene.event.HandCursorListener; import io.anuke.arc.scene.ui.*; import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.arc.util.Time; import io.anuke.mindustry.Vars; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.game.Content; @@ -40,28 +43,30 @@ public class DatabaseDialog extends FloatingDialog{ table.add("$content." + type.name() + ".name").growX().left().color(Pal.accent); table.row(); - table.addImage("white").growX().pad(5).padLeft(0).padRight(0).height(3).color(Pal.accent); + table.addImage("whiteui").growX().pad(5).padLeft(0).padRight(0).height(3).color(Pal.accent); table.row(); table.table(list -> { list.left(); int maxWidth = Core.graphics.isPortrait() ? 7 : 13; - int size = 8 * 5; int count = 0; for(int i = 0; i < array.size; i++){ UnlockableContent unlock = (UnlockableContent)array.get(i); - Image image = unlocked(unlock) ? new Image(unlock.getContentIcon()) : new Image("icon-tree-locked"); + Image image = unlocked(unlock) ? new Image(unlock.getContentIcon()) : new Image("icon-locked", Pal.gray); image.addListener(new HandCursorListener()); - list.add(image).size(size).pad(3); + list.add(image).size(unlocked(unlock) ? 8*4 : Vars.iconsize).pad(3); + ClickListener listener = new ClickListener(); + image.addListener(listener); + if(!Vars.mobile){ + image.update(() -> image.getColor().lerp(!listener.isOver() ? Color.LIGHT_GRAY : Color.WHITE, 0.4f * Time.delta())); + } if(unlocked(unlock)){ image.clicked(() -> Vars.ui.content.show(unlock)); - image.addListener(new Tooltip<>(new Table("button"){{ - add(unlock.localizedName()); - }})); + image.addListener(new Tooltip(t -> t.background("button").add(unlock.localizedName()))); } if((++count) % maxWidth == 0){ diff --git a/core/src/io/anuke/mindustry/ui/dialogs/DeployDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/DeployDialog.java index f5a17db26a..c313e12c7e 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/DeployDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/DeployDialog.java @@ -1,27 +1,25 @@ 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.collection.ObjectSet.ObjectSetIterator; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.graphics.g2d.Lines; -import io.anuke.arc.scene.Group; -import io.anuke.arc.scene.ui.TextButton; -import io.anuke.arc.scene.ui.layout.Table; -import io.anuke.arc.scene.ui.layout.Unit; -import io.anuke.arc.util.Align; -import io.anuke.arc.util.Structs; -import io.anuke.mindustry.content.Zones; -import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.game.Saves.SaveSlot; -import io.anuke.mindustry.graphics.Pal; -import io.anuke.mindustry.io.SaveIO.SaveException; -import io.anuke.mindustry.type.Zone; -import io.anuke.mindustry.type.Zone.ZoneRequirement; -import io.anuke.mindustry.ui.ItemsDisplay; -import io.anuke.mindustry.ui.TreeLayout; -import io.anuke.mindustry.ui.TreeLayout.TreeNode; +import io.anuke.arc.*; +import io.anuke.arc.collection.*; +import io.anuke.arc.collection.ObjectSet.*; +import io.anuke.arc.graphics.*; +import io.anuke.arc.graphics.g2d.*; +import io.anuke.arc.math.*; +import io.anuke.arc.math.geom.*; +import io.anuke.arc.scene.*; +import io.anuke.arc.scene.ui.*; +import io.anuke.arc.scene.ui.layout.*; +import io.anuke.arc.util.*; +import io.anuke.mindustry.content.*; +import io.anuke.mindustry.core.GameState.*; +import io.anuke.mindustry.game.Saves.*; +import io.anuke.mindustry.graphics.*; +import io.anuke.mindustry.io.SaveIO.*; +import io.anuke.mindustry.type.*; +import io.anuke.mindustry.type.Zone.*; +import io.anuke.mindustry.ui.*; +import io.anuke.mindustry.ui.TreeLayout.*; import static io.anuke.mindustry.Vars.*; @@ -29,18 +27,21 @@ public class DeployDialog extends FloatingDialog{ private final float nodeSize = Unit.dp.scl(210f); private ObjectSet nodes = new ObjectSet<>(); private ZoneInfoDialog info = new ZoneInfoDialog(); + private Rectangle bounds = new Rectangle(); public DeployDialog(){ - super(""); + super("", "fulldialog"); ZoneNode root = new ZoneNode(Zones.groundZero, null); TreeLayout layout = new TreeLayout(); layout.gapBetweenLevels = layout.gapBetweenNodes = Unit.dp.scl(50f); layout.layout(root); + bounds.set(layout.getBounds()); + bounds.y += nodeSize*0.4f; addCloseButton(); - buttons.addImageTextButton("$techtree", "icon-tree", 16 * 2, () -> ui.tech.show()).size(230f, 64f); + buttons.addImageTextButton("$techtree", "icon-tree", iconsize, () -> ui.tech.show()).size(230f, 64f); shown(this::setup); } @@ -57,48 +58,70 @@ public class DeployDialog extends FloatingDialog{ Core.settings.save(); } - cont.stack(control.saves.getZoneSlot() == null ? new View() : new Table(){{ - SaveSlot slot = control.saves.getZoneSlot(); + Stack stack = new Stack(); - TextButton[] b = {null}; + stack.add(new Image(new Texture("sprites/backgrounds/stars.png"){{ + setFilter(TextureFilter.Linear); + }}).setScaling(Scaling.fill)); - TextButton button = addButton(Core.bundle.format("resume", slot.getZone().localizedName()), () -> { - if(b[0].childrenPressed()) return; + stack.add(new Image(new Texture("sprites/backgrounds/planet-zero.png"){{ + setFilter(TextureFilter.Linear); + }}){{ + float[] time = {0}; + setColor(Color.fromGray(0.3f)); + setScale(1.5f); + update(() -> { + setOrigin(Align.center); + time[0] += Core.graphics.getDeltaTime() * 10f; + setTranslation(Mathf.sin(time[0], 60f, 70f) + panX / 30f, Mathf.cos(time[0], 140f, 80f) + (panY + 200) / 30f); + }); + }}.setScaling(Scaling.fit)); - hide(); - ui.loadAnd(() -> { - try{ - control.saves.getZoneSlot().load(); - state.set(State.playing); - }catch(SaveException e){ //make sure to handle any save load errors! - e.printStackTrace(); - if(control.saves.getZoneSlot() != null) control.saves.getZoneSlot().delete(); - Core.app.post(() -> ui.showInfo("$save.corrupted")); - show(); - } - }); - }).size(230f).get(); - b[0] = button; + if(control.saves.getZoneSlot() != null){ + stack.add(new Table(t -> { + SaveSlot slot = control.saves.getZoneSlot(); - String color = "[lightgray]"; + TextButton button = t.addButton(Core.bundle.format("resume", slot.getZone().localizedName()), () -> { - button.defaults().colspan(2); - button.row(); - button.add(Core.bundle.format("save.wave", color + slot.getWave())); - button.row(); - button.label(() -> Core.bundle.format("save.playtime", color + slot.getPlayTime())); - button.row(); - button.add().grow(); - button.row(); + hide(); + ui.loadAnd(() -> { + try{ + control.saves.getZoneSlot().load(); + state.set(State.playing); + }catch(SaveException e){ //make sure to handle any save load errors! + e.printStackTrace(); + if(control.saves.getZoneSlot() != null) control.saves.getZoneSlot().delete(); + Core.app.post(() -> ui.showInfo("$save.corrupted")); + show(); + } + }); + }).size(230f).get(); - button.addButton("$abandon", () -> { - ui.showConfirm("$warning", "$abandon.text", () -> { - slot.delete(); - setup(); - }); - }).growX().height(50f).pad(-12).padTop(10); + String color = "[lightgray]"; - }}, new ItemsDisplay()).grow(); + button.defaults().colspan(2); + button.row(); + button.add(Core.bundle.format("save.wave", color + slot.getWave())); + button.row(); + button.label(() -> Core.bundle.format("save.playtime", color + slot.getPlayTime())); + button.row(); + + t.row(); + + t.addButton("$abandon", () -> { + ui.showConfirm("$warning", "$abandon.text", () -> { + slot.delete(); + setup(); + }); + }).width(230f).height(50f).padTop(3); + })); + }else{ + stack.add(new View()); + } + + stack.add(new ItemsDisplay()); + + cont.add(stack).grow(); //set up direct and indirect children for(ZoneNode node : nodes){ @@ -131,10 +154,10 @@ public class DeployDialog extends FloatingDialog{ button.clicked(() -> info.show(zone)); if(zone.unlocked()){ - button.addImage("icon-zone").padRight(3); + button.addImage("icon-terrain").size(iconsize).padRight(3); button.labelWrap(zone.localizedName()).width(140).growX(); }else{ - button.addImage("icon-zone-locked"); + button.addImage("icon-locked"); button.row(); button.add("$locked"); } @@ -160,16 +183,30 @@ public class DeployDialog extends FloatingDialog{ dragged((x, y) -> { panX += x; panY += y; + clamp(); }); } + void clamp(){ + float pad = nodeSize; + + float ox = width/2f, oy = height/2f; + float rx = bounds.x + panX + ox, ry = panY + oy + bounds.y; + float rw = bounds.width, rh = bounds.height; + rx = Mathf.clamp(rx, -rw + pad, Core.graphics.getWidth() - pad); + ry = Mathf.clamp(ry, pad, Core.graphics.getHeight() - rh - pad); + panX = rx - bounds.x - ox; + panY = ry - bounds.y - oy; + } + @Override public void draw(){ + clamp(); float offsetX = panX + width / 2f + x, offsetY = panY + height / 2f + y; for(ZoneNode node : nodes){ for(ZoneNode child : node.allChildren){ - Lines.stroke(Unit.dp.scl(3f), node.zone.locked() || child.zone.locked() ? Pal.locked : Pal.accent); + Lines.stroke(Unit.dp.scl(3f), node.zone.locked() || child.zone.locked() ? Pal.gray : 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/dialogs/DiscordDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/DiscordDialog.java index a38ffa4af7..c7c343c6c6 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/DiscordDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/DiscordDialog.java @@ -5,8 +5,7 @@ import io.anuke.arc.graphics.Color; import io.anuke.arc.scene.ui.Dialog; import io.anuke.mindustry.graphics.Pal; -import static io.anuke.mindustry.Vars.discordURL; -import static io.anuke.mindustry.Vars.ui; +import static io.anuke.mindustry.Vars.*; public class DiscordDialog extends Dialog{ @@ -23,14 +22,14 @@ public class DiscordDialog extends Dialog{ t.background("button").margin(0); t.table(img -> { - img.addImage("white").height(h - 5).width(40f).color(color); + img.addImage("whiteui").height(h - 5).width(40f).color(color); img.row(); - img.addImage("white").height(5).width(40f).color(color.cpy().mul(0.8f, 0.8f, 0.8f, 1f)); + img.addImage("whiteui").height(5).width(40f).color(color.cpy().mul(0.8f, 0.8f, 0.8f, 1f)); }).expandY(); t.table(i -> { i.background("button"); - i.addImage("icon-discord").size(14 * 3); + i.addImage("icon-discord").size(iconsize); }).size(h).left(); t.add("$discord").color(Pal.accent).growX().padLeft(10f); @@ -40,12 +39,12 @@ public class DiscordDialog extends Dialog{ buttons.addButton("$back", this::hide); buttons.addButton("$copylink", () -> { - Core.app.getClipboard().setContents(discordURL); + Core.app.setClipboardText(discordURL); }); buttons.addButton("$openlink", () -> { if(!Core.net.openURI(discordURL)){ ui.showError("$linkfail"); - Core.app.getClipboard().setContents(discordURL); + Core.app.setClipboardText(discordURL); } }); } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/FileChooser.java b/core/src/io/anuke/mindustry/ui/dialogs/FileChooser.java index 89317ab552..d76a25a981 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/FileChooser.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/FileChooser.java @@ -12,11 +12,12 @@ import io.anuke.arc.scene.ui.layout.Table; import io.anuke.arc.scene.ui.layout.Unit; import io.anuke.arc.util.*; import io.anuke.arc.util.pooling.Pools; -import io.anuke.mindustry.Vars; import io.anuke.mindustry.core.Platform; import java.util.Arrays; +import static io.anuke.mindustry.Vars.*; + public class FileChooser extends FloatingDialog{ private static final FileHandle homeDirectory = Core.files.absolute(OS.isMac ? OS.getProperty("user.home") + "/Downloads/" : Core.files.getExternalStoragePath()); private static FileHandle lastDirectory = homeDirectory; @@ -33,9 +34,9 @@ public class FileChooser extends FloatingDialog{ private int lastWidth = Core.graphics.getWidth(), lastHeight = Core.graphics.getHeight(); public static final Predicate pngFiles = str -> str.equals("png"); - public static final Predicate anyMapFiles = str -> str.equals(Vars.oldMapExtension) || str.equals(Vars.mapExtension); - public static final Predicate mapFiles = str -> str.equals(Vars.mapExtension); - public static final Predicate saveFiles = str -> str.equals(Vars.saveExtension); + public static final Predicate anyMapFiles = str -> str.equals(oldMapExtension) || str.equals(mapExtension); + public static final Predicate mapFiles = str -> str.equals(mapExtension); + public static final Predicate saveFiles = str -> str.equals(saveExtension); public FileChooser(String title, Predicate filter, boolean open, Consumer result){ super(title); @@ -99,7 +100,7 @@ public class FileChooser extends FloatingDialog{ Table icontable = new Table(); - float isize = 14 * 2; + float isize = iconsize; ImageButton up = new ImageButton("icon-folder-parent"); up.resizeImage(isize); @@ -131,7 +132,7 @@ public class FileChooser extends FloatingDialog{ updateFiles(true); }); - icontable.defaults().height(50).growX().padTop(5).uniform(); + icontable.defaults().height(60).growX().padTop(5).uniform(); icontable.add(home); icontable.add(back); icontable.add(forward); @@ -142,7 +143,7 @@ public class FileChooser extends FloatingDialog{ fieldcontent.add(filefield).height(40f).fillX().expandX().padLeft(10f); Table buttons = new Table(); - buttons.defaults().growX().height(50); + buttons.defaults().growX().height(60); buttons.add(cancel); buttons.add(ok); @@ -213,7 +214,7 @@ public class FileChooser extends FloatingDialog{ updateFiles(true); }); - upbutton.left().add(upimage).padRight(4f).size(14 * 2); + upbutton.left().add(upimage).padRight(4f).size(iconsize); upbutton.getLabel().setAlignment(Align.left); upbutton.getCells().reverse(); @@ -249,7 +250,7 @@ public class FileChooser extends FloatingDialog{ Image image = new Image(file.isDirectory() ? "icon-folder" : "icon-file-text"); - button.add(image).padRight(4f).size(14 * 2f); + button.add(image).padRight(4f).size(iconsize); button.getCells().reverse(); files.top().left().add(button).align(Align.topLeft).fillX().expandX() .height(50).pad(2).padTop(0).padBottom(0).colspan(2); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/FloatingDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/FloatingDialog.java index 967fda7db8..7910a4ddd6 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/FloatingDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/FloatingDialog.java @@ -11,18 +11,19 @@ import io.anuke.mindustry.game.EventType.ResizeEvent; import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.net.Net; +import static io.anuke.mindustry.Vars.iconsize; import static io.anuke.mindustry.Vars.state; public class FloatingDialog extends Dialog{ private boolean wasPaused; protected boolean shouldPause; - public FloatingDialog(String title){ - super(title, "dialog"); + public FloatingDialog(String title, String style){ + super(title, style); setFillParent(true); this.title.setAlignment(Align.center); titleTable.row(); - titleTable.addImage("white", Pal.accent) + titleTable.addImage("whiteui", Pal.accent) .growX().height(3f).pad(4f); hidden(() -> { @@ -53,6 +54,10 @@ public class FloatingDialog extends Dialog{ }))); } + public FloatingDialog(String title){ + this(title, "dialog"); + } + protected void onResize(Runnable run){ Events.on(ResizeEvent.class, event -> { if(isShown()){ @@ -63,7 +68,7 @@ public class FloatingDialog extends Dialog{ @Override public void addCloseButton(){ - buttons.addImageTextButton("$back", "icon-arrow-left", 30f, this::hide).size(210f, 64f); + buttons.addImageTextButton("$back", "icon-arrow-left", iconsize, this::hide).size(210f, 64f); keyDown(key -> { if(key == KeyCode.ESCAPE || key == KeyCode.BACK){ diff --git a/core/src/io/anuke/mindustry/ui/dialogs/HostDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/HostDialog.java index dacb8fe5e4..485d4c3d21 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/HostDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/HostDialog.java @@ -30,7 +30,7 @@ public class HostDialog extends FloatingDialog{ ui.listfrag.rebuild(); }).grow().pad(8).get().setMaxLength(40); - ImageButton button = t.addImageButton("white", "clear-full", 40, () -> { + ImageButton button = t.addImageButton("whiteui", "clear-full", 40, () -> { new ColorPickDialog().show(color -> { player.color.set(color); Core.settings.put("color-0", Color.rgba8888(color)); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/JoinDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/JoinDialog.java index 65c7e22137..9b5f6de9f7 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/JoinDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/JoinDialog.java @@ -97,7 +97,7 @@ public class JoinDialog extends FloatingDialog{ if(!buttons[0].childrenPressed()){ connect(server.ip, server.port); } - }).width(targetWidth()).height(155f).pad(4f).get(); + }).width(targetWidth()).height(130f).pad(4f).get(); button.getLabel().setWrap(true); @@ -107,16 +107,35 @@ public class JoinDialog extends FloatingDialog{ inner.add(button.getLabel()).growX(); - inner.addImageButton("icon-loading", "empty", 16 * 2, () -> { + inner.addImageButton("icon-arrow-up-small", "empty", iconsizesmall, () -> { + int index = servers.indexOf(server); + if(index > 0){ + servers.remove(index); + servers.insert(0, server); + + saveServers(); + setupRemote(); + for(Server other : servers){ + if(other.lastHost != null){ + setupServer(other, other.lastHost); + }else{ + refreshServer(other); + } + } + } + + }).margin(3f).padTop(6f).top().right(); + + inner.addImageButton("icon-loading-small", "empty", iconsizesmall, () -> { refreshServer(server); }).margin(3f).padTop(6f).top().right(); - inner.addImageButton("icon-pencil", "empty", 16 * 2, () -> { + inner.addImageButton("icon-pencil-small", "empty", iconsizesmall, () -> { renaming = server; add.show(); }).margin(3f).padTop(6f).top().right(); - inner.addImageButton("icon-trash-16", "empty", 16 * 2, () -> { + inner.addImageButton("icon-trash-16-small", "empty", iconsizesmall, () -> { ui.showConfirm("$confirm", "$server.delete", () -> { servers.removeValue(server, true); saveServers(); @@ -144,42 +163,41 @@ public class JoinDialog extends FloatingDialog{ server.content.clear(); server.content.label(() -> Core.bundle.get("server.refreshing") + Strings.animated(Time.time(), 4, 11, ".")); - Net.pingHost(server.ip, server.port, host -> { - String versionString; - - if(host.version == -1){ - versionString = Core.bundle.format("server.version", Core.bundle.get("server.custombuild"), ""); - }else if(host.version == 0){ - versionString = Core.bundle.get("server.outdated"); - }else if(host.version < Version.build && Version.build != -1){ - versionString = Core.bundle.get("server.outdated") + "\n" + - Core.bundle.format("server.version", host.version, ""); - }else if(host.version > Version.build && Version.build != -1){ - versionString = Core.bundle.get("server.outdated.client") + "\n" + - Core.bundle.format("server.version", host.version, ""); - }else{ - versionString = Core.bundle.format("server.version", host.version, host.versionType); - } - - server.content.clear(); - - server.content.table(t -> { - t.add("[lightgray]" + host.name).width(targetWidth() - 10f).left().get().setEllipsis(true); - t.row(); - t.add(versionString).left(); - t.row(); - t.add("[lightgray]" + (host.players != 1 ? Core.bundle.format("players", host.players) : - Core.bundle.format("players.single", host.players))).left(); - t.row(); - t.add("[lightgray]" + Core.bundle.format("save.map", host.mapname) + " / " + Core.bundle.format("save.wave", host.wave)).width(targetWidth() - 10f).left().get().setEllipsis(true); - }).expand().left().bottom().padLeft(12f).padBottom(8); - - }, e -> { + Net.pingHost(server.ip, server.port, host -> setupServer(server, host), e -> { server.content.clear(); server.content.add("$host.invalid"); }); } + void setupServer(Server server, Host host){ + server.lastHost = host; + String versionString; + + if(host.version == -1){ + versionString = Core.bundle.format("server.version", Core.bundle.get("server.custombuild"), ""); + }else if(host.version == 0){ + versionString = Core.bundle.get("server.outdated"); + }else if(host.version < Version.build && Version.build != -1){ + versionString = Core.bundle.get("server.outdated") + "\n" + + Core.bundle.format("server.version", host.version, ""); + }else if(host.version > Version.build && Version.build != -1){ + versionString = Core.bundle.get("server.outdated.client") + "\n" + + Core.bundle.format("server.version", host.version, ""); + }else{ + versionString = Core.bundle.format("server.version", host.version, host.versionType); + } + + server.content.clear(); + + server.content.table(t -> { + t.add("[lightgray]" + host.name + " " + versionString).width(targetWidth() - 10f).left().get().setEllipsis(true); + t.row(); + t.add("[lightgray]" + (host.players != 1 ? Core.bundle.format("players", host.players == 0 ? host.players : "[accent]" + host.players + "[lightgray]") : Core.bundle.format("players.single", "[accent]" + host.players + "[lightgray]"))).left(); + t.row(); + t.add("[lightgray]" + Core.bundle.format("save.map", host.mapname) + "[lightgray] / " + Core.bundle.format("save.wave", host.wave)).width(targetWidth() - 10f).left().get().setEllipsis(true); + }).expand().left().bottom().padLeft(12f).padBottom(8); + } + void setup(){ float w = targetWidth(); @@ -205,7 +223,7 @@ public class JoinDialog extends FloatingDialog{ Core.settings.save(); }).grow().pad(8).get().setMaxLength(maxNameLength); - ImageButton button = t.addImageButton("white", "clear-full", 40, () -> { + ImageButton button = t.addImageButton("whiteui", "clear-full", 40, () -> { new ColorPickDialog().show(color -> { player.color.set(color); Core.settings.put("color-0", Color.rgba8888(color)); @@ -217,7 +235,7 @@ public class JoinDialog extends FloatingDialog{ cont.row(); cont.add(pane).width(w + 38).pad(0); cont.row(); - cont.addCenteredImageTextButton("$server.add", "icon-add", 14 * 3, () -> { + cont.addCenteredImageTextButton("$server.add", "icon-add", iconsize, () -> { renaming = null; add.show(); }).marginLeft(6).width(w).height(80f).update(button -> { @@ -230,7 +248,7 @@ public class JoinDialog extends FloatingDialog{ Cell cell = ((Table)pane.getParent()).getCell(button); - if(!Mathf.isEqual(cell.getMinWidth(), pw)){ + if(!Mathf.isEqual(cell.minWidth(), pw)){ cell.width(pw); cell.padLeft(pad); pane.getParent().invalidateHierarchy(); @@ -253,7 +271,7 @@ public class JoinDialog extends FloatingDialog{ local.background("button"); local.add("$hosts.none").pad(10f); local.add().growX(); - local.addImageButton("icon-loading", 16 * 2f, this::refreshLocal).pad(-12f).padLeft(0).size(70f); + local.addImageButton("icon-loading", iconsize, this::refreshLocal).pad(-12f).padLeft(0).size(70f); }else{ local.background((Drawable)null); } @@ -320,6 +338,7 @@ public class JoinDialog extends FloatingDialog{ public int port; transient Table content; + transient Host lastHost; void setIP(String ip){ diff --git a/core/src/io/anuke/mindustry/ui/dialogs/LanguageDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/LanguageDialog.java index 25040a0a03..f1a1a15ac2 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/LanguageDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/LanguageDialog.java @@ -29,7 +29,7 @@ public class LanguageDialog extends FloatingDialog{ ButtonGroup group = new ButtonGroup<>(); for(Locale loc : locales){ - TextButton button = new TextButton(Strings.capitalize(loc.getDisplayName(loc)), "toggle"); + TextButton button = new TextButton(Strings.capitalize(loc.getDisplayName(loc)), "clear-toggle"); button.clicked(() -> { if(getLocale().equals(loc)) return; Core.settings.put("locale", loc.toString()); @@ -37,7 +37,7 @@ public class LanguageDialog extends FloatingDialog{ Log.info("Setting locale: {0}", loc.toString()); ui.showInfo("$language.restart"); }); - langs.add(button).group(group).update(t -> t.setChecked(loc.equals(getLocale()))).size(400f, 50f).pad(2).row(); + langs.add(button).group(group).update(t -> t.setChecked(loc.equals(getLocale()))).size(400f, 50f).row(); } cont.add(pane); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/LoadDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/LoadDialog.java index 880dfb3eb5..e0103b2bbd 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/LoadDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/LoadDialog.java @@ -65,25 +65,25 @@ public class LoadDialog extends FloatingDialog{ button.table(t -> { t.right(); - t.addImageButton("icon-floppy", "emptytoggle", 14 * 3, () -> { + t.addImageButton("icon-floppy", "emptytoggle", iconsize, () -> { slot.setAutosave(!slot.isAutosave()); }).checked(slot.isAutosave()).right(); - t.addImageButton("icon-trash", "empty", 14 * 3, () -> { + t.addImageButton("icon-trash", "empty", iconsize, () -> { ui.showConfirm("$confirm", "$save.delete.confirm", () -> { slot.delete(); setup(); }); - }).size(14 * 3).right(); + }).size(iconsize).right(); - t.addImageButton("icon-pencil-small", "empty", 14 * 3, () -> { + t.addImageButton("icon-pencil", "empty", iconsize, () -> { ui.showTextInput("$save.rename", "$save.rename.text", slot.getName(), text -> { slot.setName(text); setup(); }); - }).size(14 * 3).right(); + }).size(iconsize).right(); - t.addImageButton("icon-save", "empty", 14 * 3, () -> { + t.addImageButton("icon-save", "empty", iconsize, () -> { if(!ios){ Platform.instance.showFileChooser(Core.bundle.get("save.export"), "Mindustry Save", file -> { try{ @@ -102,7 +102,7 @@ public class LoadDialog extends FloatingDialog{ ui.showError(Core.bundle.format("save.export.fail", Strings.parseException(e, true))); } } - }).size(14 * 3).right(); + }).size(iconsize).right(); }).padRight(-10).growX(); @@ -147,7 +147,7 @@ public class LoadDialog extends FloatingDialog{ if(ios) return; - slots.addImageTextButton("$save.import", "icon-add", 14 * 3, () -> { + slots.addImageTextButton("$save.import", "icon-add", iconsize, () -> { Platform.instance.showFileChooser(Core.bundle.get("save.import"), "Mindustry Save", file -> { if(SaveIO.isSaveValid(file)){ try{ diff --git a/core/src/io/anuke/mindustry/ui/dialogs/ZoneLoadoutDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/LoadoutDialog.java similarity index 58% rename from core/src/io/anuke/mindustry/ui/dialogs/ZoneLoadoutDialog.java rename to core/src/io/anuke/mindustry/ui/dialogs/LoadoutDialog.java index f4de558ae8..64a588de1d 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/ZoneLoadoutDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/LoadoutDialog.java @@ -1,16 +1,22 @@ package io.anuke.mindustry.ui.dialogs; +import io.anuke.arc.collection.Array; +import io.anuke.arc.function.Predicate; +import io.anuke.arc.function.Supplier; import io.anuke.arc.scene.ui.TextButton; import io.anuke.mindustry.type.*; import static io.anuke.mindustry.Vars.content; -import static io.anuke.mindustry.Vars.data; -public class ZoneLoadoutDialog extends FloatingDialog{ - private Zone zone; +public class LoadoutDialog extends FloatingDialog{ private Runnable hider; + private Supplier> supplier; + private Runnable resetter; + private Runnable updater; + private Predicate filter; + private int capacity; - public ZoneLoadoutDialog(){ + public LoadoutDialog(){ super("$configure"); setFillParent(false); addCloseButton(); @@ -22,15 +28,19 @@ public class ZoneLoadoutDialog extends FloatingDialog{ }); buttons.row(); buttons.addButton("$settings.reset", () -> { - zone.resetStartingItems(); - zone.updateLaunchCost(); + resetter.run(); + updater.run(); setup(); }).size(210f, 64f); } - public void show(Zone zone, Runnable hider){ + public void show(int capacity, Supplier> supplier, Runnable reseter, Runnable updater, Runnable hider, Predicate filter){ + this.resetter = reseter; + this.supplier = supplier; + this.updater = updater; + this.capacity = capacity; this.hider = hider; - this.zone = zone; + this.filter = filter; show(); } @@ -39,20 +49,20 @@ public class ZoneLoadoutDialog extends FloatingDialog{ float bsize = 40f; int step = 50; - for(ItemStack stack : zone.getStartingItems()){ + for(ItemStack stack : supplier.get()){ cont.addButton("x", "clear-partial", () -> { - zone.getStartingItems().remove(stack); - zone.updateLaunchCost(); + supplier.get().remove(stack); + updater.run(); setup(); }).size(bsize); cont.addButton("-", "clear-partial", () -> { stack.amount = Math.max(stack.amount - step, 0); - zone.updateLaunchCost(); + updater.run(); }).size(bsize); cont.addButton("+", "clear-partial", () -> { - stack.amount = Math.min(stack.amount + step, zone.loadout.core().itemCapacity); - zone.updateLaunchCost(); + stack.amount = Math.min(stack.amount + step, capacity); + updater.run(); }).size(bsize); cont.addImage(stack.item.icon(Item.Icon.medium)).size(8 * 3).padRight(4); @@ -64,10 +74,10 @@ public class ZoneLoadoutDialog extends FloatingDialog{ cont.addButton("$add", () -> { FloatingDialog dialog = new FloatingDialog(""); dialog.setFillParent(false); - for(Item item : content.items().select(item -> data.getItem(item) > 0 && item.type == ItemType.material && zone.getStartingItems().find(stack -> stack.item == item) == null)){ + for(Item item : content.items().select(item -> filter.test(item) && item.type == ItemType.material && supplier.get().find(stack -> stack.item == item) == null)){ TextButton button = dialog.cont.addButton("", "clear", () -> { - zone.getStartingItems().add(new ItemStack(item, 0)); - zone.updateLaunchCost(); + supplier.get().add(new ItemStack(item, 0)); + updater.run(); setup(); dialog.hide(); }).size(300f, 36f).get(); @@ -78,7 +88,7 @@ public class ZoneLoadoutDialog extends FloatingDialog{ dialog.cont.row(); } dialog.show(); - }).colspan(4).size(100f, bsize).left().disabled(b -> !content.items().contains(item -> data.getItem(item) > 0 && item.type == ItemType.material && !zone.getStartingItems().contains(stack -> stack.item == item))); + }).colspan(4).size(100f, bsize).left().disabled(b -> !content.items().contains(item -> filter.test(item) && !supplier.get().contains(stack -> stack.item == item))); pack(); } } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/MapPlayDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/MapPlayDialog.java index e2938b143a..1bc7051710 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/MapPlayDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/MapPlayDialog.java @@ -1,11 +1,9 @@ package io.anuke.mindustry.ui.dialogs; import io.anuke.arc.Core; -import io.anuke.arc.math.Mathf; -import io.anuke.arc.scene.event.Touchable; import io.anuke.arc.scene.ui.ScrollPane; import io.anuke.arc.scene.ui.layout.Table; -import io.anuke.arc.util.Scaling; +import io.anuke.arc.util.*; import io.anuke.mindustry.game.*; import io.anuke.mindustry.maps.Map; import io.anuke.mindustry.ui.BorderImage; @@ -13,21 +11,33 @@ import io.anuke.mindustry.ui.BorderImage; import static io.anuke.mindustry.Vars.*; public class MapPlayDialog extends FloatingDialog{ - Difficulty difficulty = Difficulty.normal; CustomRulesDialog dialog = new CustomRulesDialog(); Rules rules; Gamemode selectedGamemode = Gamemode.survival; + Map lastMap; public MapPlayDialog(){ super(""); setFillParent(false); + + onResize(() -> { + if(lastMap != null){ + show(lastMap); + } + }); } public void show(Map map){ + this.lastMap = map; title.setText(map.name()); cont.clearChildren(); - rules = map.rules(); + //reset to any valid mode after switching to attack (one must exist) + if(!selectedGamemode.valid(map)){ + selectedGamemode = Structs.find(Gamemode.all, m -> m.valid(map)); + } + + rules = map.rules(); rules = selectedGamemode.apply(map.rules()); Table selmode = new Table(); @@ -40,14 +50,10 @@ public class MapPlayDialog extends FloatingDialog{ for(Gamemode mode : Gamemode.values()){ if(mode.hidden) continue; - if((mode == Gamemode.attack && !map.hasEnemyCore()) || (mode == Gamemode.pvp && !map.hasOtherCores())){ - continue; - } - modes.addButton(mode.toString(), "toggle", () -> { selectedGamemode = mode; rules = mode.apply(map.rules()); - }).update(b -> b.setChecked(selectedGamemode == mode)).size(140f, 54f); + }).update(b -> b.setChecked(selectedGamemode == mode)).size(140f, 54f).disabled(!mode.valid(map)); if(i++ % 2 == 1) modes.row(); } selmode.add(modes); @@ -55,40 +61,19 @@ public class MapPlayDialog extends FloatingDialog{ cont.add(selmode); cont.row(); - - Difficulty[] ds = Difficulty.values(); - - float s = 50f; - - Table sdif = new Table(); - - sdif.add("$setting.difficulty.name").colspan(3); - sdif.row(); - sdif.defaults().height(s + 4); - sdif.addImageButton("icon-arrow-left", 10 * 3, () -> { - difficulty = (ds[Mathf.mod(difficulty.ordinal() - 1, ds.length)]); - state.wavetime = difficulty.waveTime; - }).width(s); - - sdif.addButton("", () -> {}).update(t -> { - t.setText(difficulty.toString()); - t.touchable(Touchable.disabled); - }).width(180f); - - sdif.addImageButton("icon-arrow-right", 10 * 3, () -> { - difficulty = (ds[Mathf.mod(difficulty.ordinal() + 1, ds.length)]); - state.wavetime = difficulty.waveTime; - }).width(s); - sdif.addButton("$customize", () -> dialog.show(rules, () -> rules = (selectedGamemode == null ? map.rules() : selectedGamemode.apply(map.rules())))).width(140).padLeft(10); - - cont.add(sdif); + cont.addImageTextButton("$customize", "icon-tools-small", iconsizesmall, () -> dialog.show(rules, () -> rules = (selectedGamemode == null ? map.rules() : selectedGamemode.apply(map.rules())))).width(230); cont.row(); cont.add(new BorderImage(map.texture, 3f)).size(mobile && !Core.graphics.isPortrait() ? 150f : 250f).get().setScaling(Scaling.fit); + //only maps with survival are valid for high scores + if(Gamemode.survival.valid(map)){ + cont.row(); + cont.label((() -> Core.bundle.format("level.highscore", map.getHightScore()))).pad(3f); + } buttons.clearChildren(); addCloseButton(); - buttons.addImageTextButton("$play", "icon-play", 8*3, () -> { + buttons.addImageTextButton("$play", "icon-play", iconsize, () -> { control.playMap(map, rules); hide(); ui.custom.hide(); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java index aefa5e64c9..a59850a88d 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/MapsDialog.java @@ -1,16 +1,19 @@ package io.anuke.mindustry.ui.dialogs; -import io.anuke.arc.Core; -import io.anuke.arc.graphics.Color; -import io.anuke.arc.scene.event.Touchable; +import io.anuke.arc.*; +import io.anuke.arc.graphics.*; +import io.anuke.arc.input.*; +import io.anuke.arc.math.*; +import io.anuke.arc.scene.event.*; import io.anuke.arc.scene.ui.*; -import io.anuke.arc.scene.ui.layout.Table; -import io.anuke.arc.util.Scaling; -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.ui.BorderImage; +import io.anuke.arc.scene.ui.layout.*; +import io.anuke.arc.util.*; +import io.anuke.mindustry.*; +import io.anuke.mindustry.core.*; +import io.anuke.mindustry.graphics.*; +import io.anuke.mindustry.io.*; +import io.anuke.mindustry.maps.*; +import io.anuke.mindustry.ui.*; import static io.anuke.mindustry.Vars.*; @@ -20,8 +23,44 @@ public class MapsDialog extends FloatingDialog{ public MapsDialog(){ super("$maps"); - addCloseButton(); - buttons.addImageTextButton("$editor.importmap", "icon-add", 14 * 2, () -> { + buttons.remove(); + + keyDown(key -> { + if(key == KeyCode.ESCAPE || key == KeyCode.BACK){ + Core.app.post(this::hide); + } + }); + + shown(this::setup); + onResize(() -> { + if(dialog != null){ + dialog.hide(); + } + setup(); + }); + } + + void setup(){ + buttons.clearChildren(); + + if(Core.graphics.isPortrait()){ + buttons.addImageTextButton("$back", "icon-arrow-left", iconsize, this::hide).size(210f*2f, 64f).colspan(2); + buttons.row(); + }else{ + buttons.addImageTextButton("$back", "icon-arrow-left", iconsize, this::hide).size(210f, 64f); + } + + buttons.addImageTextButton("$editor.newmap", "icon-add", iconsize, () -> { + ui.showTextInput("$editor.newmap", "$name", "", text -> { + ui.loadAnd(() -> { + hide(); + ui.editor.show(); + ui.editor.editor.getTags().put("name", text); + }); + }); + }).size(210f, 64f); + + buttons.addImageTextButton("$editor.importmap", "icon-load", iconsize, () -> { Platform.instance.showFileChooser("$editor.importmap", "Map File", file -> { world.maps.tryCatchMapError(() -> { if(MapIO.isImage(file)){ @@ -60,17 +99,8 @@ public class MapsDialog extends FloatingDialog{ }); }, true, FileChooser.anyMapFiles); - }).size(230f, 64f); + }).size(210f, 64f); - shown(this::setup); - onResize(() -> { - if(dialog != null){ - dialog.hide(); - } - }); - } - - void setup(){ cont.clear(); Table maps = new Table(); @@ -79,7 +109,7 @@ public class MapsDialog extends FloatingDialog{ ScrollPane pane = new ScrollPane(maps); pane.setFadeScrollBars(false); - int maxwidth = 4; + int maxwidth = Mathf.clamp((int)(Core.graphics.getWidth() / Unit.dp.scl(230)), 1, 8); float mapsize = 200f; int i = 0; @@ -94,7 +124,7 @@ public class MapsDialog extends FloatingDialog{ button.margin(9); button.add(map.name()).width(mapsize - 18f).center().get().setEllipsis(true); button.row(); - button.addImage("white").growX().pad(4).color(Color.GRAY); + button.addImage("whiteui").growX().pad(4).color(Pal.gray); button.row(); button.stack(new Image(map.texture).setScaling(Scaling.fit), new BorderImage(map.texture).setScaling(Scaling.fit)).size(mapsize - 20f); button.row(); @@ -107,6 +137,8 @@ public class MapsDialog extends FloatingDialog{ maps.add("$maps.none"); } + cont.add(buttons).growX(); + cont.row(); cont.add(pane).uniformX(); } @@ -145,7 +177,7 @@ public class MapsDialog extends FloatingDialog{ table.row(); - table.addImageTextButton("$editor.openin", "icon-load-map", 16 * 2, () -> { + table.addImageTextButton("$editor.openin", "icon-load-map-small", iconsizesmall, () -> { try{ Vars.ui.editor.beginEditMap(map.file); dialog.hide(); @@ -156,7 +188,7 @@ public class MapsDialog extends FloatingDialog{ } }).fillX().height(54f).marginLeft(10); - table.addImageTextButton("$delete", "icon-trash-16", 16 * 2, () -> { + table.addImageTextButton("$delete", "icon-trash-16-small", iconsizesmall, () -> { ui.showConfirm("$confirm", Core.bundle.format("map.delete", map.name()), () -> { world.maps.removeMap(map); dialog.hide(); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/MinimapDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/MinimapDialog.java index 111d102232..5a59074ed8 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/MinimapDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/MinimapDialog.java @@ -9,7 +9,6 @@ import io.anuke.arc.scene.event.InputListener; import io.anuke.arc.scene.ui.layout.Unit; import static io.anuke.mindustry.Vars.*; -import static io.anuke.mindustry.Vars.world; public class MinimapDialog extends FloatingDialog{ diff --git a/core/src/io/anuke/mindustry/ui/dialogs/PausedDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/PausedDialog.java index 5b72cba724..0a8a004d85 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/PausedDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/PausedDialog.java @@ -10,6 +10,7 @@ import static io.anuke.mindustry.Vars.*; public class PausedDialog extends FloatingDialog{ private SaveDialog save = new SaveDialog(); private LoadDialog load = new LoadDialog(); + private boolean wasClient = false; public PausedDialog(){ super("$menu"); @@ -55,13 +56,12 @@ public class PausedDialog extends FloatingDialog{ cont.row(); - if(!state.isEditor()){ - cont.addButton("$hostserver", ui.host::show).disabled(b -> Net.active()).colspan(2).width(dw * 2 + 20f); - cont.row(); - } + cont.addButton("$hostserver", ui.host::show).disabled(b -> Net.active()).colspan(2).width(dw * 2 + 20f); + cont.row(); cont.addButton("$quit", () -> { ui.showConfirm("$confirm", "$quit.confirm", () -> { + wasClient = Net.client(); if(Net.client()) netClient.disconnectQuietly(); runExitSave(); hide(); @@ -70,7 +70,7 @@ public class PausedDialog extends FloatingDialog{ }else{ cont.defaults().size(120f).pad(5); - float isize = 14f * 4; + float isize = iconsize; cont.addRowImageTextButton("$back", "icon-play-2", isize, this::hide); cont.addRowImageTextButton("$settings", "icon-tools", isize, ui.settings::show); @@ -85,11 +85,11 @@ public class PausedDialog extends FloatingDialog{ cont.row(); } - if(!state.isEditor()){ - cont.addRowImageTextButton("$hostserver.mobile", "icon-host", isize, ui.host::show).disabled(b -> Net.active()); - } + cont.addRowImageTextButton("$hostserver.mobile", "icon-host", isize, ui.host::show).disabled(b -> Net.active()); + cont.addRowImageTextButton("$quit", "icon-quit", isize, () -> { ui.showConfirm("$confirm", "$quit.confirm", () -> { + wasClient = Net.client(); if(Net.client()) netClient.disconnectQuietly(); runExitSave(); hide(); @@ -99,7 +99,7 @@ public class PausedDialog extends FloatingDialog{ } public void runExitSave(){ - if(state.isEditor()){ + if(state.isEditor() && !wasClient){ ui.editor.resumeEditing(); return; } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/SaveDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/SaveDialog.java index 004a1fafe5..1a3966b4d1 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/SaveDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/SaveDialog.java @@ -23,7 +23,7 @@ public class SaveDialog extends LoadDialog{ public void addSetup(){ slots.row(); slots.addImageTextButton("$save.new", "icon-add", 14 * 3, () -> - ui.showTextInput("$save", "$save.newslot", "", text -> { + ui.showTextInput("$save", "$save.newslot", 30, "", text -> { ui.loadAnd("$saving", () -> { control.saves.addSave(text); Core.app.post(() -> Core.app.post(this::setup)); diff --git a/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java index ac19e1a480..4d0c13284c 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/SettingsMenuDialog.java @@ -11,8 +11,7 @@ import io.anuke.arc.scene.event.InputListener; import io.anuke.arc.scene.ui.*; import io.anuke.arc.scene.ui.SettingsDialog.SettingsTable.Setting; import io.anuke.arc.scene.ui.layout.Table; -import io.anuke.arc.util.Align; -import io.anuke.mindustry.Vars; +import io.anuke.arc.util.*; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.core.Platform; import io.anuke.mindustry.graphics.Pal; @@ -44,22 +43,24 @@ public class SettingsMenuDialog extends SettingsDialog{ wasPaused = state.is(State.paused); state.set(State.paused); } + + rebuildMenu(); }); setFillParent(true); title.setAlignment(Align.center); titleTable.row(); - titleTable.add(new Image("white")).growX().height(3f).pad(4f).get().setColor(Pal.accent); + titleTable.add(new Image("whiteui")).growX().height(3f).pad(4f).get().setColor(Pal.accent); cont.clearChildren(); cont.remove(); buttons.remove(); - menu = new Table(); + menu = new Table("button"); Consumer s = table -> { table.row(); - table.addImageTextButton("$back", "icon-arrow-left", 10 * 3, this::back).size(240f, 60f).colspan(2).padTop(15f); + table.addImageTextButton("$back", "icon-arrow-left", iconsize, this::back).size(240f, 60f).colspan(2).padTop(15f); }; game = new SettingsTable(s); @@ -70,18 +71,7 @@ public class SettingsMenuDialog extends SettingsDialog{ prefs.top(); prefs.margin(14f); - menu.defaults().size(300f, 60f).pad(3f); - menu.addButton("$settings.game", () -> visible(0)); - menu.row(); - menu.addButton("$settings.graphics", () -> visible(1)); - menu.row(); - menu.addButton("$settings.sound", () -> visible(2)); - if(!Vars.mobile){ - menu.row(); - menu.addButton("$settings.controls", ui.controls::show); - } - menu.row(); - menu.addButton("$settings.language", ui.language::show); + rebuildMenu(); prefs.clearChildren(); prefs.add(menu); @@ -117,15 +107,34 @@ public class SettingsMenuDialog extends SettingsDialog{ addSettings(); } + void rebuildMenu(){ + menu.clearChildren(); + + String style = "clear"; + + menu.defaults().size(300f, 60f); + menu.addButton("$settings.game", style, () -> visible(0)); + menu.row(); + menu.addButton("$settings.graphics", style, () -> visible(1)); + menu.row(); + menu.addButton("$settings.sound", style, () -> visible(2)); + menu.row(); + menu.addButton("$settings.language", style, ui.language::show); + if(!mobile || Core.settings.getBool("keyboard")){ + menu.row(); + menu.addButton("$settings.controls", style, ui.controls::show); + } + } + 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); if(mobile){ game.checkPref("autotarget", true); + game.checkPref("keyboard", false); } game.sliderPref("saveinterval", 60, 10, 5 * 120, i -> Core.bundle.format("setting.seconds", i)); @@ -175,7 +184,14 @@ public class SettingsMenuDialog extends SettingsDialog{ } }); - graphics.sliderPref("fpscap", 125, 5, 125, 5, s -> (s > 120 ? Core.bundle.get("setting.fpscap.none") : Core.bundle.format("setting.fpscap.text", s))); + graphics.sliderPref("uiscale", 100, 25, 400, 25, s -> { + if(Core.graphics.getFrameId() > 10){ + Log.info("changed"); + Core.settings.put("uiscalechanged", true); + } + return s + "%"; + }); + graphics.sliderPref("fpscap", 241, 5, 241, 5, s -> (s > 240 ? Core.bundle.get("setting.fpscap.none") : Core.bundle.format("setting.fpscap.text", s))); graphics.sliderPref("chatopacity", 100, 0, 100, 5, s -> s + "%"); if(!mobile){ @@ -192,11 +208,11 @@ public class SettingsMenuDialog extends SettingsDialog{ Core.graphics.setVSync(Core.settings.getBool("vsync")); if(Core.settings.getBool("fullscreen")){ - Core.graphics.setFullscreenMode(Core.graphics.getDisplayMode()); + Core.app.post(() -> Core.graphics.setFullscreenMode(Core.graphics.getDisplayMode())); } if(Core.settings.getBool("borderlesswindow")){ - Core.graphics.setUndecorated(true); + Core.app.post(() -> Core.graphics.setUndecorated(true)); } }else{ graphics.checkPref("landscape", false, b -> { @@ -212,12 +228,14 @@ public class SettingsMenuDialog extends SettingsDialog{ } } + graphics.checkPref("effects", true); graphics.checkPref("playerchat", true); graphics.checkPref("minimap", !mobile); graphics.checkPref("fps", false); graphics.checkPref("indicators", true); graphics.checkPref("animatedwater", false); graphics.checkPref("animatedshields", !mobile); + graphics.checkPref("bloom", false, val -> renderer.toggleBloom(val)); graphics.checkPref("lasers", true); graphics.checkPref("pixelate", false); @@ -239,6 +257,7 @@ public class SettingsMenuDialog extends SettingsDialog{ } private void back(){ + rebuildMenu(); prefs.clearChildren(); prefs.add(menu); } diff --git a/core/src/io/anuke/mindustry/ui/dialogs/TechTreeDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/TechTreeDialog.java index 601de99218..caf670a280 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/TechTreeDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/TechTreeDialog.java @@ -1,30 +1,25 @@ 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.actions.RelativeTemporalAction; -import io.anuke.arc.scene.event.Touchable; -import io.anuke.arc.scene.style.TextureRegionDrawable; -import io.anuke.arc.scene.ui.ImageButton; -import io.anuke.arc.scene.ui.layout.Table; -import io.anuke.arc.scene.ui.layout.Unit; -import io.anuke.arc.util.Align; -import io.anuke.mindustry.content.TechTree; -import io.anuke.mindustry.content.TechTree.TechNode; -import io.anuke.mindustry.graphics.Pal; -import io.anuke.mindustry.type.ItemStack; -import io.anuke.mindustry.ui.ItemsDisplay; -import io.anuke.mindustry.ui.TreeLayout; -import io.anuke.mindustry.ui.TreeLayout.TreeNode; -import io.anuke.mindustry.world.Block.Icon; +import io.anuke.arc.*; +import io.anuke.arc.collection.*; +import io.anuke.arc.graphics.*; +import io.anuke.arc.graphics.g2d.*; +import io.anuke.arc.math.*; +import io.anuke.arc.math.geom.*; +import io.anuke.arc.scene.*; +import io.anuke.arc.scene.actions.*; +import io.anuke.arc.scene.event.*; +import io.anuke.arc.scene.style.*; +import io.anuke.arc.scene.ui.*; +import io.anuke.arc.scene.ui.layout.*; +import io.anuke.arc.util.*; +import io.anuke.mindustry.content.*; +import io.anuke.mindustry.content.TechTree.*; +import io.anuke.mindustry.graphics.*; +import io.anuke.mindustry.type.*; +import io.anuke.mindustry.ui.*; +import io.anuke.mindustry.ui.TreeLayout.*; +import io.anuke.mindustry.world.Block.*; import static io.anuke.mindustry.Vars.*; @@ -32,6 +27,7 @@ public class TechTreeDialog extends FloatingDialog{ private final float nodeSize = Unit.dp.scl(60f); private ObjectSet nodes = new ObjectSet<>(); private TechTreeNode root = new TechTreeNode(TechTree.root, null); + private Rectangle bounds = new Rectangle(); private ItemsDisplay items; public TechTreeDialog(){ @@ -50,7 +46,7 @@ public class TechTreeDialog extends FloatingDialog{ addCloseButton(); - buttons.addImageTextButton("$database", "icon-database", 14 * 2, () -> { + buttons.addImageTextButton("$database", "icon-database", iconsize, () -> { hide(); ui.database.show(); }).size(210f, 64f); @@ -67,6 +63,8 @@ public class TechTreeDialog extends FloatingDialog{ layout.gapBetweenNodes = Unit.dp.scl(40f); LayoutNode node = new LayoutNode(root, null); layout.layout(node); + bounds.set(layout.getBounds()); + bounds.y += nodeSize*1.5f; copyInfo(node); } @@ -192,9 +190,9 @@ public class TechTreeDialog extends FloatingDialog{ button.update(() -> { float offset = (Core.graphics.getHeight() % 2) / 2f; button.setPosition(node.x + panX + width / 2f, node.y + panY + height / 2f + offset, Align.center); - button.getStyle().up = Core.scene.skin.getDrawable(!locked(node.node) ? "content-background" : !data.hasItems(node.node.requirements) ? "content-background-noitems" : "content-background-locked"); + button.getStyle().up = Core.scene.skin.getDrawable(!locked(node.node) ? "button-over" : !data.hasItems(node.node.requirements) ? "button-red" : "button"); ((TextureRegionDrawable)button.getStyle().imageUp) - .setRegion(node.visible ? node.node.block.icon(Icon.medium) : Core.atlas.find("icon-tree-locked")); + .setRegion(node.visible ? node.node.block.icon(Icon.medium) : Core.atlas.find("icon-locked")); button.getImage().setColor(!locked(node.node) ? Color.WHITE : Color.GRAY); }); addChild(button); @@ -214,9 +212,22 @@ public class TechTreeDialog extends FloatingDialog{ moved = true; panX += x; panY += y; + clamp(); }); } + void clamp(){ + float pad = nodeSize; + + float ox = width/2f, oy = height/2f; + float rx = bounds.x + panX + ox, ry = panY + oy + bounds.y; + float rw = bounds.width, rh = bounds.height; + rx = Mathf.clamp(rx, -rw + pad, Core.graphics.getWidth() - pad); + ry = Mathf.clamp(ry, pad, Core.graphics.getHeight() - rh - pad); + panX = rx - bounds.x - ox; + panY = ry - bounds.y - oy; + } + void unlock(TechNode node){ data.unlockContent(node.block); data.removeItems(node.requirements); @@ -246,44 +257,52 @@ public class TechTreeDialog extends FloatingDialog{ } }); - infoTable.background("content-background"); infoTable.update(() -> infoTable.setPosition(button.getX() + button.getWidth(), button.getY() + button.getHeight(), Align.topLeft)); - infoTable.margin(0).left().defaults().left(); + infoTable.left(); + infoTable.background("button").margin(8f); - infoTable.addImageButton("icon-info", "node", 14 * 2, () -> ui.content.show(node.block)).growY().width(50f); + infoTable.table(b -> { + b.margin(0).left().defaults().left(); - infoTable.add().grow(); + b.addImageButton("icon-info-small", "clear", iconsizesmall, () -> ui.content.show(node.block)).growY().width(50f); + b.add().grow(); + b.table(desc -> { + desc.left().defaults().left(); + desc.add(node.block.localizedName); + desc.row(); + if(locked(node)){ + desc.table(t -> { + t.left(); + for(ItemStack req : node.requirements){ + t.table(list -> { + list.left(); + list.addImage(req.item.icon(Item.Icon.medium)).size(8 * 3).padRight(3); + list.add(req.item.localizedName()).color(Color.LIGHT_GRAY); + list.label(() -> " " + Math.min(data.getItem(req.item), req.amount) + " / " + req.amount) + .update(l -> l.setColor(data.has(req.item, req.amount) ? Color.LIGHT_GRAY : Color.SCARLET)); + }).fillX().left(); + t.row(); + } + }); + }else{ + desc.add("$completed"); + } + }).pad(9); - infoTable.table(desc -> { - desc.left().defaults().left(); - desc.add(node.block.localizedName); - desc.row(); - if(locked(node)){ - desc.table(t -> { - t.left(); - for(ItemStack req : node.requirements){ - t.table(list -> { - list.left(); - list.addImage(req.item.getContentIcon()).size(8 * 3).padRight(3); - list.add(req.item.localizedName()).color(Color.LIGHT_GRAY); - list.label(() -> " " + Math.min(data.getItem(req.item), req.amount) + " / " + req.amount) - .update(l -> l.setColor(data.has(req.item, req.amount) ? Color.LIGHT_GRAY : Color.SCARLET)); - }).fillX().left(); - t.row(); - } - }); - }else{ - desc.add("$completed"); + if(mobile && locked(node)){ + b.row(); + b.addImageTextButton("$research", "icon-check-small", "node", iconsizesmall, () -> unlock(node)) + .disabled(i -> !data.hasItems(node.requirements)).growX().height(44f).colspan(3); } - }).pad(9); + }); - if(mobile && locked(node)){ - infoTable.row(); - infoTable.addImageTextButton("$research", "icon-check", "node", 16 * 2, () -> unlock(node)) - .disabled(b -> !data.hasItems(node.requirements)).growX().height(44f).colspan(3); + infoTable.row(); + if(node.block.description != null){ + infoTable.table(t -> t.margin(3f).left().labelWrap(node.block.description).color(Color.LIGHT_GRAY).growX()).fillX(); } + addChild(infoTable); infoTable.pack(); infoTable.act(Core.graphics.getDeltaTime()); @@ -291,6 +310,7 @@ public class TechTreeDialog extends FloatingDialog{ @Override public void draw(){ + clamp(); float offsetX = panX + width / 2f + x, offsetY = panY + height / 2f + y; for(TechTreeNode node : nodes){ @@ -298,7 +318,7 @@ public class TechTreeDialog extends FloatingDialog{ for(TechTreeNode child : node.children){ if(!child.visible) continue; - Lines.stroke(Unit.dp.scl(3f), locked(node.node) || locked(child.node) ? Pal.locked : Pal.accent); + Lines.stroke(Unit.dp.scl(4f), locked(node.node) || locked(child.node) ? Pal.gray : 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/dialogs/ZoneInfoDialog.java b/core/src/io/anuke/mindustry/ui/dialogs/ZoneInfoDialog.java index 99b03b803d..1ff99705c4 100644 --- a/core/src/io/anuke/mindustry/ui/dialogs/ZoneInfoDialog.java +++ b/core/src/io/anuke/mindustry/ui/dialogs/ZoneInfoDialog.java @@ -4,6 +4,7 @@ import io.anuke.arc.Core; import io.anuke.arc.graphics.Color; import io.anuke.arc.scene.ui.Button; import io.anuke.arc.scene.ui.layout.Table; +import io.anuke.mindustry.game.*; import io.anuke.mindustry.graphics.Pal; import io.anuke.mindustry.type.*; import io.anuke.mindustry.type.Zone.ZoneRequirement; @@ -13,7 +14,7 @@ import io.anuke.mindustry.world.Block.Icon; import static io.anuke.mindustry.Vars.*; public class ZoneInfoDialog extends FloatingDialog{ - private ZoneLoadoutDialog loadout = new ZoneLoadoutDialog(); + private LoadoutDialog loadout = new LoadoutDialog(); public ZoneInfoDialog(){ super(""); @@ -58,7 +59,7 @@ public class ZoneInfoDialog extends FloatingDialog{ cont.table(cont -> { if(zone.locked()){ - cont.addImage("icon-zone-locked"); + cont.addImage("icon-locked"); cont.row(); cont.add("$locked").padBottom(6); cont.row(); @@ -71,10 +72,9 @@ public class ZoneInfoDialog extends FloatingDialog{ r.add("$complete").colspan(2).left(); r.row(); for(ZoneRequirement other : zone.zoneRequirements){ - r.addImage("icon-zone").padRight(4); + r.addImage("icon-terrain").padRight(4); r.add(Core.bundle.format("zone.requirement", other.wave, other.zone.localizedName())).color(Color.LIGHT_GRAY); - r.addImage(other.zone.bestWave() >= other.wave ? "icon-check-2" : "icon-cancel-2") - .color(other.zone.bestWave() >= other.wave ? Color.LIGHT_GRAY : Color.SCARLET).padLeft(3); + r.addImage(other.zone.bestWave() >= other.wave ? "icon-check-small" : "icon-cancel-small", other.zone.bestWave() >= other.wave ? Color.LIGHT_GRAY : Color.SCARLET).padLeft(3); r.row(); } }); @@ -89,8 +89,7 @@ public class ZoneInfoDialog extends FloatingDialog{ for(Block block : zone.blockRequirements){ r.addImage(block.icon(Icon.small)).size(8 * 3).padRight(4); r.add(block.localizedName).color(Color.LIGHT_GRAY); - r.addImage(data.isUnlocked(block) ? "icon-check-2" : "icon-cancel-2") - .color(data.isUnlocked(block) ? Color.LIGHT_GRAY : Color.SCARLET).padLeft(3); + r.addImage(data.isUnlocked(block) ? "icon-check-small" : "icon-cancel-small", data.isUnlocked(block) ? Color.LIGHT_GRAY : Color.SCARLET).padLeft(3); r.row(); } @@ -101,25 +100,42 @@ public class ZoneInfoDialog extends FloatingDialog{ }else{ cont.add(zone.localizedName()).color(Pal.accent).growX().center(); cont.row(); - cont.addImage("white").color(Pal.accent).height(3).pad(6).growX(); + cont.addImage("whiteui").color(Pal.accent).height(3).pad(6).growX(); cont.row(); - cont.addButton(zone.canConfigure() ? "$configure" : Core.bundle.format("configure.locked", zone.configureWave), () -> loadout.show(zone, rebuildItems)).fillX().pad(3).disabled(b -> !zone.canConfigure()); - cont.row(); - cont.table(res -> { - res.add("$zone.resources").padRight(6); - if(zone.resources.length > 0){ - for(Item item : zone.resources){ - res.addImage(item.icon(Item.Icon.medium)).size(8 * 3); + cont.table(desc -> { + desc.left().defaults().left().width(Core.graphics.isPortrait() ? 350f : 500f); + desc.pane(t -> t.marginRight(12f).add(zone.description).wrap().growX()).fillX().maxHeight(mobile ? 240f : 400f).pad(2).padBottom(8f).get().setScrollingDisabled(true, false); + desc.row(); + + desc.table(t -> { + t.left(); + t.add("$zone.resources").padRight(6); + + if(zone.resources.length > 0){ + for(Item item : zone.resources){ + t.addImage(item.icon(Item.Icon.medium)).size(8 * 3); + } + }else{ + t.add("$none"); } - }else{ - res.add("$none"); + }); + + Rules rules = zone.getRules(); + + desc.row(); + desc.add(Core.bundle.format("zone.objective", Core.bundle.get(!rules.attackMode ? "zone.objective.survival" : "zone.objective.attack"))); + + if(zone.bestWave() > 0){ + desc.row(); + desc.add(Core.bundle.format("bestwave", zone.bestWave())); } }); - if(zone.bestWave() > 0){ - cont.row(); - cont.add(Core.bundle.format("bestwave", zone.bestWave())); - } + cont.row(); + + cont.addButton(zone.canConfigure() ? "$configure" : Core.bundle.format("configure.locked", zone.configureWave), + () -> loadout.show(zone.loadout.core().itemCapacity, zone::getStartingItems, zone::resetStartingItems, zone::updateLaunchCost, rebuildItems, item -> data.getItem(item) > 0 && item.type == ItemType.material) + ).fillX().pad(3).disabled(b -> !zone.canConfigure()); } }); cont.row(); diff --git a/core/src/io/anuke/mindustry/ui/fragments/BackgroundFragment.java b/core/src/io/anuke/mindustry/ui/fragments/BackgroundFragment.java deleted file mode 100644 index 1914fbf8fa..0000000000 --- a/core/src/io/anuke/mindustry/ui/fragments/BackgroundFragment.java +++ /dev/null @@ -1,33 +0,0 @@ -package io.anuke.mindustry.ui.fragments; - -import io.anuke.arc.Core; -import io.anuke.arc.graphics.g2d.*; -import io.anuke.arc.scene.Group; -import io.anuke.arc.scene.ui.layout.Unit; -import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.graphics.Shaders; - -import static io.anuke.mindustry.Vars.state; - -public class BackgroundFragment extends Fragment{ - - @Override - public void build(Group parent){ - Core.scene.table().addRect((a, b, w, h) -> { - Draw.colorl(0.1f); - Fill.crect(0, 0, w, h); - Draw.shader(Shaders.menu); - Fill.crect(0, 0, w, h); - Draw.shader(); - - boolean portrait = Core.graphics.getWidth() < Core.graphics.getHeight(); - float logoscl = (int)Unit.dp.scl(1); - TextureRegion logo = Core.atlas.find("logotext"); - float logow = logo.getWidth() * logoscl; - float logoh = logo.getHeight() * logoscl; - - Draw.color(); - Draw.rect(logo, (int)(w / 2), (int)(h - 10 - logoh - Unit.dp.scl(portrait ? 30f : 0)) + logoh / 2, logow, logoh); - }).visible(() -> state.is(State.menu)).grow(); - } -} diff --git a/core/src/io/anuke/mindustry/ui/fragments/BlockConfigFragment.java b/core/src/io/anuke/mindustry/ui/fragments/BlockConfigFragment.java index 392a73c352..b41dd8ea40 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/BlockConfigFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/BlockConfigFragment.java @@ -24,6 +24,19 @@ public class BlockConfigFragment extends Fragment{ public void build(Group parent){ table.visible(false); parent.addChild(table); + + //hacky way to hide block config when in menu + //TODO remove? + Core.scene.add(new Element(){ + @Override + public void act(float delta){ + super.act(delta); + if(state.is(State.menu)){ + table.visible(false); + configTile = null; + } + } + }); } public boolean isShown(){ @@ -47,11 +60,6 @@ public class BlockConfigFragment extends Fragment{ Actions.scaleTo(1f, 1f, 0.07f, Interpolation.pow3Out)); table.update(() -> { - if(state.is(State.menu)){ - hideConfig(); - return; - } - if(configTile != null && configTile.block().shouldHideConfigure(configTile, player)){ hideConfig(); return; diff --git a/core/src/io/anuke/mindustry/ui/fragments/BlockInventoryFragment.java b/core/src/io/anuke/mindustry/ui/fragments/BlockInventoryFragment.java index d0a86d0f3c..b7da02cdf2 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/BlockInventoryFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/BlockInventoryFragment.java @@ -52,7 +52,7 @@ public class BlockInventoryFragment extends Fragment{ @Override public void build(Group parent){ table = new Table(); - table.visible(() -> !state.is(State.menu)); + table.setName("inventory"); table.setTransform(true); parent.setTransform(true); parent.addChild(table); @@ -70,10 +70,11 @@ public class BlockInventoryFragment extends Fragment{ } public void hide(){ - table.actions(Actions.scaleTo(0f, 1f, 0.06f, Interpolation.pow3Out), Actions.visible(false), Actions.run(() -> { - table.clear(); + table.actions(Actions.scaleTo(0f, 1f, 0.06f, Interpolation.pow3Out), Actions.run(() -> { + table.clearChildren(); + table.clearListeners(); table.update(null); - })); + }), Actions.visible(false)); table.touchable(Touchable.disabled); tile = null; } @@ -83,9 +84,11 @@ public class BlockInventoryFragment extends Fragment{ IntSet container = new IntSet(); table.clearChildren(); + table.clearActions(); table.background("inventory"); table.touchable(Touchable.enabled); table.update(() -> { + if(state.is(State.menu) || tile == null || tile.entity == null || !tile.block().isAccessible() || tile.entity.items.total() == 0){ hide(); }else{ @@ -115,8 +118,8 @@ public class BlockInventoryFragment extends Fragment{ int cols = 3; int row = 0; - table.margin(6f); - table.defaults().size(8 * 5).space(8f); + table.margin(4f); + table.defaults().size(8 * 5).pad(4f); if(tile.block().hasItems){ @@ -171,9 +174,13 @@ public class BlockInventoryFragment extends Fragment{ updateTablePosition(); + table.visible(true); + if(actions){ - table.actions(Actions.scaleTo(0f, 1f), Actions.visible(true), - Actions.scaleTo(1f, 1f, 0.07f, Interpolation.pow3Out)); + table.setScale(0f, 1f); + table.actions(Actions.scaleTo(1f, 1f, 0.07f, Interpolation.pow3Out)); + }else{ + table.setScale(1f, 1f); } } diff --git a/core/src/io/anuke/mindustry/ui/fragments/ChatFragment.java b/core/src/io/anuke/mindustry/ui/fragments/ChatFragment.java index f2bcf3ea48..28b1eff9ba 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/ChatFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/ChatFragment.java @@ -15,14 +15,14 @@ import io.anuke.arc.scene.ui.layout.Unit; import io.anuke.arc.util.Align; import io.anuke.arc.util.Time; import io.anuke.mindustry.Vars; -import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.input.Binding; import io.anuke.mindustry.net.Net; import static io.anuke.arc.Core.input; import static io.anuke.arc.Core.scene; -import static io.anuke.mindustry.Vars.*; +import static io.anuke.mindustry.Vars.maxTextLength; +import static io.anuke.mindustry.Vars.mobile; public class ChatFragment extends Table{ private final static int messagesShown = 10; @@ -61,7 +61,7 @@ public class ChatFragment extends Table{ } } - return !state.is(State.menu) && Net.active(); + return Net.active(); }); update(() -> { diff --git a/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java b/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java index fbee21cea9..2a34a372fb 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/HudFragment.java @@ -1,5 +1,7 @@ package io.anuke.mindustry.ui.fragments; +import io.anuke.annotations.Annotations.Loc; +import io.anuke.annotations.Annotations.Remote; import io.anuke.arc.Core; import io.anuke.arc.Events; import io.anuke.arc.collection.Array; @@ -19,11 +21,10 @@ import io.anuke.arc.scene.ui.*; import io.anuke.arc.scene.ui.layout.*; import io.anuke.arc.scene.utils.Elements; import io.anuke.arc.util.*; -import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.core.GameState.State; -import io.anuke.mindustry.entities.Effects; import io.anuke.mindustry.entities.Units; import io.anuke.mindustry.entities.type.BaseUnit; +import io.anuke.mindustry.entities.type.Player; import io.anuke.mindustry.game.EventType.StateChangeEvent; import io.anuke.mindustry.game.Team; import io.anuke.mindustry.game.UnlockableContent; @@ -47,31 +48,32 @@ public class HudFragment extends Fragment{ private Table lastUnlockLayout; private boolean shown = true; private float dsize = 59; - private float isize = 40; private float coreAttackTime; private float lastCoreHP; + private Team lastTeam; private float coreAttackOpacity = 0f; public void build(Group parent){ //menu at top left parent.fill(cont -> { - cont.top().left().visible(() -> !state.is(State.menu)); + cont.top().left(); if(mobile){ { Table select = new Table(); - select.visible(() -> !state.is(State.menu)); select.left(); select.defaults().size(dsize).left(); - select.addImageButton("icon-menu", "clear", isize, ui.paused::show); - flip = select.addImageButton("icon-arrow-up", "clear", isize, this::toggleMenus).get(); + String style = "clear-trans"; - select.addImageButton("icon-pause", "clear", isize, () -> { + select.addImageButton("icon-menu-large", style, iconsize, ui.paused::show); + flip = select.addImageButton("icon-arrow-up", style, iconsize, this::toggleMenus).get(); + + select.addImageButton("icon-pause", style, iconsize, () -> { if(Net.active()){ ui.listfrag.toggle(); }else{ @@ -86,7 +88,7 @@ public class HudFragment extends Fragment{ } }).get(); - select.addImageButton("icon-settings", "clear", isize, () -> { + select.addImageButton("icon-settings", style, iconsize, () -> { if(Net.active() && mobile){ if(ui.chatfrag.chatOpen()){ ui.chatfrag.hide(); @@ -102,27 +104,28 @@ public class HudFragment extends Fragment{ if(Net.active() && mobile){ i.getStyle().imageUp = Core.scene.skin.getDrawable("icon-chat"); }else{ - i.getStyle().imageUp = Core.scene.skin.getDrawable("icon-database-small"); + i.getStyle().imageUp = Core.scene.skin.getDrawable("icon-database"); } }).get(); - select.addImage("blank").color(Pal.accent).width(3f).fillY(); + select.addImage("whiteui").color(Pal.gray).width(4f).fillY(); float size = Unit.dp.scl(dsize); Array children = new Array<>(select.getChildren()); + //now, you may be wondering, why is this necessary? the answer is, I don't know, but it fixes layout issues somehow int index = 0; for(Element elem : children){ int fi = index++; - Core.scene.add(elem); + parent.addChild(elem); elem.visible(() -> { if(fi < 4){ elem.setSize(size); }else{ - elem.setSize(3f, size); + elem.setSize(Unit.dp.scl(4f), size); } elem.setPosition(fi * size, Core.graphics.getHeight(), Align.topLeft); - return !state.is(State.menu); + return true; }); } @@ -130,19 +133,26 @@ public class HudFragment extends Fragment{ } cont.row(); - cont.addImage("blank").height(3f).color(Pal.accent).fillX(); + cont.addImage("whiteui").height(4f).color(Pal.gray).fillX(); cont.row(); } cont.update(() -> { - if(!Core.input.keyDown(Binding.gridMode) && Core.input.keyTap(Binding.toggle_menus) && !ui.chatfrag.chatOpen()){ + if(!Core.input.keyDown(Binding.gridMode) && Core.input.keyTap(Binding.toggle_menus) && !ui.chatfrag.chatOpen() && !Core.scene.hasDialog() && !(Core.scene.getKeyboardFocus() instanceof TextField)){ toggleMenus(); } }); Table wavesMain, editorMain; + boolean[] prev = {false}; - cont.stack(wavesMain = new Table(), editorMain = new Table()).height(e -> wavesMain.isVisible() ? wavesMain.getPrefHeight() : editorMain.getPrefHeight()); + cont.stack(wavesMain = new Table(), editorMain = new Table()).height(wavesMain.getPrefHeight()).update(s -> { + ((Table)s.getParent()).getCell(s).height((wavesMain.isVisible() ? wavesMain.getPrefHeight() : editorMain.getPrefHeight()) / Unit.dp.scl(1f)); + if(prev[0] != wavesMain.isVisible()){ + s.getParent().pack(); + prev[0] = wavesMain.isVisible(); + } + }); { wavesMain.visible(() -> shown && !state.isEditor()); @@ -156,7 +166,7 @@ public class HudFragment extends Fragment{ addWaveTable(waves); addPlayButton(btable); - wavesMain.add(stack).width(dsize * 4 + 3f); + wavesMain.add(stack).width(dsize * 4 + 4f); wavesMain.row(); wavesMain.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(() -> state.rules.waves && state.boss() != null).height(60f).get(); @@ -172,7 +182,7 @@ public class HudFragment extends Fragment{ teams.left(); int i = 0; for(Team team : Team.all){ - ImageButton button = teams.addImageButton("white", "clear-toggle-partial", 40f, () -> player.setTeam(team)) + ImageButton button = teams.addImageButton("white", "clear-toggle-partial", 40f, () -> Call.setPlayerTeamEditor(player, team)) .size(50f).margin(6f).get(); button.getImageCell().grow(); button.getStyle().imageUpColor = team.color; @@ -184,68 +194,59 @@ public class HudFragment extends Fragment{ } }).left(); - t.row(); - t.addImageTextButton("$editor.spawn", "icon-add", 8*3, () -> { - FloatingDialog dialog = new FloatingDialog("$editor.spawn"); - int i = 0; - for(UnitType type : content.getBy(ContentType.unit)){ - dialog.cont.addImageButton("white", 48, () -> { - BaseUnit unit = type.create(player.getTeam()); - unit.set(player.x, player.y); - unit.rotation = player.rotation; - unit.add(); - //trigger the entity to become visible - unitGroups[player.getTeam().ordinal()].updateEvents(); - collisions.updatePhysics( unitGroups[player.getTeam().ordinal()]); - dialog.hide(); - }).get().getStyle().imageUp = new TextureRegionDrawable(type.iconRegion); - if(++i % 4 == 0) dialog.cont.row(); - } - dialog.addCloseButton(); - dialog.setFillParent(false); - dialog.show(); - }).fillX(); + if(enableUnitEditing){ - float[] size = {0}; - float[] position = {0, 0}; - - t.row(); - t.addImageTextButton("$editor.removeunit", "icon-quit", "toggle", 8*3, () -> { - - }).fillX().update(b -> { - boolean[] found = {false}; - if(b.isChecked()){ - Element e = Core.scene.hit(Core.input.mouseX(), Core.input.mouseY(), true); - if(e == null){ - Vector2 world = Core.input.mouseWorld(); - Units.nearby(world.x, world.y, 1f, 1f, unit -> { - if(!found[0] && unit instanceof BaseUnit){ - if(Core.input.keyTap(KeyCode.MOUSE_LEFT)){ - Effects.effect(Fx.spawn, unit); - unit.remove(); - unitGroups[unit.getTeam().ordinal()].updateEvents(); - collisions.updatePhysics(unitGroups[unit.getTeam().ordinal()]); - } - found[0] = true; - unit.hitbox(Tmp.r1); - size[0] = Mathf.lerpDelta(size[0], Tmp.r1.width*2f + Mathf.absin(Time.time(), 10f, 5f), 0.1f); - position[0] = unit.x; - position[1] = unit.y; - } - }); - //TODO check for unit removal, remove unit if needed + t.row(); + t.addImageTextButton("$editor.spawn", "icon-add", iconsize, () -> { + FloatingDialog dialog = new FloatingDialog("$editor.spawn"); + int i = 0; + for(UnitType type : content.getBy(ContentType.unit)){ + dialog.cont.addImageButton("white", 48, () -> { + Call.spawnUnitEditor(player, type); + dialog.hide(); + }).get().getStyle().imageUp = new TextureRegionDrawable(type.iconRegion); + if(++i % 4 == 0) dialog.cont.row(); } - } + dialog.addCloseButton(); + dialog.setFillParent(false); + dialog.show(); + }).fillX(); - Draw.color(Pal.accent, Color.WHITE, Mathf.absin(Time.time(), 8f, 1f)); - Lines.poly(position[0], position[1], 4, size[0]/2f); - Draw.reset(); + float[] size = {0}; + float[] position = {0, 0}; - if(!found[0]){ - size[0] = Mathf.lerpDelta(size[0], 0f, 0.2f); - } - }); - }).width(dsize * 4 + 3f); + t.row(); + t.addImageTextButton("$editor.removeunit", "icon-quit", "toggle", iconsize, () -> {}).fillX().update(b -> { + boolean[] found = {false}; + if(b.isChecked()){ + Element e = Core.scene.hit(Core.input.mouseX(), Core.input.mouseY(), true); + if(e == null){ + Vector2 world = Core.input.mouseWorld(); + Units.nearby(world.x, world.y, 1f, 1f, unit -> { + if(!found[0] && unit instanceof BaseUnit){ + if(Core.input.keyTap(KeyCode.MOUSE_LEFT)){ + Call.removeUnitEditor(player, (BaseUnit)unit); + } + found[0] = true; + unit.hitbox(Tmp.r1); + size[0] = Mathf.lerpDelta(size[0], Tmp.r1.width * 2f + Mathf.absin(Time.time(), 10f, 5f), 0.1f); + position[0] = unit.x; + position[1] = unit.y; + } + }); + } + } + + Draw.color(Pal.accent, Color.WHITE, Mathf.absin(Time.time(), 8f, 1f)); + Lines.poly(position[0], position[1], 4, size[0] / 2f); + Draw.reset(); + + if(!found[0]){ + size[0] = Mathf.lerpDelta(size[0], 0f, 0.2f); + } + }); + } + }).width(dsize * 4 + 4f); editorMain.visible(() -> shown && state.isEditor()); } @@ -263,33 +264,19 @@ public class HudFragment extends Fragment{ }); //minimap - parent.fill(t -> t.top().right().add(new Minimap()).visible(() -> !state.is(State.menu) && Core.settings.getBool("minimap"))); + parent.fill(t -> t.top().right().add(new Minimap()).visible(() -> Core.settings.getBool("minimap"))); //spawner warning parent.fill(t -> { t.touchable(Touchable.disabled); - t.visible(() -> !state.is(State.menu)); t.table("flat", c -> c.add("$nearpoint") .update(l -> l.setColor(Tmp.c1.set(Color.WHITE).lerp(Color.SCARLET, Mathf.absin(Time.time(), 10f, 1f)))) .get().setAlignment(Align.center, Align.center)) .margin(6).update(u -> u.color.a = Mathf.lerpDelta(u.color.a, Mathf.num(world.spawner.playerNear()), 0.1f)).get().color.a = 0f; }); - //out of bounds warning parent.fill(t -> { - t.touchable(Touchable.disabled); - t.visible(() -> !state.is(State.menu)); - t.table("flat", c -> c.add("") - .update(l -> { - l.setColor(Tmp.c1.set(Color.WHITE).lerp(Color.SCARLET, Mathf.absin(Time.time(), 10f, 1f))); - l.setText(Core.bundle.format("outofbounds", (int)((boundsCountdown - player.destructTime) / 60f))); - }).get().setAlignment(Align.center, Align.center)).margin(6).update(u -> { - u.color.a = Mathf.lerpDelta(u.color.a, Mathf.num(player.isOutOfBounds()), 0.1f); - }).get().color.a = 0f; - }); - - parent.fill(t -> { - t.visible(() -> netServer.isWaitingForPlayers() && !state.is(State.menu)); + t.visible(() -> netServer.isWaitingForPlayers()); t.table("button", c -> c.add("$waiting.players")); }); @@ -306,13 +293,19 @@ public class HudFragment extends Fragment{ }); t.top().visible(() -> { - if(state.is(State.menu) || state.teams.get(player.getTeam()).cores.size == 0 || - state.teams.get(player.getTeam()).cores.first().entity == null){ + if(state.is(State.menu) || state.teams.get(player.getTeam()).cores.size == 0 || state.teams.get(player.getTeam()).cores.first().entity == null){ coreAttackTime = 0f; return false; } float curr = state.teams.get(player.getTeam()).cores.first().entity.health; + + if(lastTeam != player.getTeam()){ + lastCoreHP = curr; + lastTeam = player.getTeam(); + return false; + } + if(!Float.isNaN(lastCoreHP) && curr < lastCoreHP){ coreAttackTime = notifDuration; } @@ -326,6 +319,7 @@ public class HudFragment extends Fragment{ } coreAttackTime -= Time.delta(); + lastTeam = player.getTeam(); return coreAttackOpacity > 0; }); @@ -335,7 +329,7 @@ public class HudFragment extends Fragment{ //launch button parent.fill(t -> { - t.top().right().visible(() -> !state.is(State.menu)); + t.top().right(); TextButton[] testb = {null}; TextButton button = Elements.newButton("$launch", () -> { FloatingDialog dialog = new FloatingDialog("$launch"); @@ -363,10 +357,10 @@ public class HudFragment extends Fragment{ button.getStyle().disabledFontColor = Color.WHITE; button.margin(16f); button.visible(() -> - world.isZone() && - world.getZone().metCondition() && - !Net.client() && - state.wave % world.getZone().launchPeriod == 0 && !world.spawner.isSpawning()); + world.isZone() && + world.getZone().metCondition() && + !Net.client() && + state.wave % world.getZone().launchPeriod == 0 && !world.spawner.isSpawning()); button.update(() -> { if(world.getZone() == null){ @@ -388,17 +382,41 @@ public class HudFragment extends Fragment{ //paused table parent.fill(t -> { - t.top().visible(() -> state.is(State.paused) && !Net.active()); + t.top().visible(() -> state.isPaused()); t.table("button", top -> top.add("$paused").pad(6f)); }); //'saving' indicator parent.fill(t -> { - t.bottom().visible(() -> !state.is(State.menu) && control.saves.isSaving()); + t.bottom().visible(() -> control.saves.isSaving()); t.add("$saveload"); }); - blockfrag.build(Core.scene.root); + blockfrag.build(parent); + } + + @Remote(targets = Loc.both, forward = true, called = Loc.both) + public static void setPlayerTeamEditor(Player player, Team team){ + if(state.isEditor()){ + player.setTeam(team); + } + } + + @Remote(targets = Loc.both, called = Loc.server) + public static void spawnUnitEditor(Player player, UnitType type){ + if(state.isEditor()){ + BaseUnit unit = type.create(player.getTeam()); + unit.set(player.x, player.y); + unit.rotation = player.rotation; + unit.add(); + } + } + + @Remote(targets = Loc.both, called = Loc.server, forward = true) + public static void removeUnitEditor(Player player, BaseUnit unit){ + if(state.isEditor() && unit != null){ + unit.remove(); + } } public void showToast(String text){ @@ -409,7 +427,7 @@ public class HudFragment extends Fragment{ } }); table.margin(12); - table.addImage("icon-check").size(16 * 2).pad(3); + table.addImage("icon-check").size(iconsize).pad(3); table.add(text).wrap().width(280f).get().setAlignment(Align.center, Align.center); table.pack(); @@ -512,7 +530,7 @@ public class HudFragment extends Fragment{ } public void showLaunch(){ - Image image = new Image("white"); + Image image = new Image("whiteui"); image.getColor().a = 0f; image.setFillParent(true); image.actions(Actions.fadeIn(40f / 60f)); @@ -530,14 +548,33 @@ public class HudFragment extends Fragment{ } shown = !shown; + if(flip != null){ + flip.getParent().act(Core.graphics.getDeltaTime()); + } } private void addWaveTable(TextButton table){ + StringBuilder ibuild = new StringBuilder(); IntFormat wavef = new IntFormat("wave"); IntFormat enemyf = new IntFormat("wave.enemy"); IntFormat enemiesf = new IntFormat("wave.enemies"); - IntFormat waitingf = new IntFormat("wave.waiting"); + IntFormat waitingf = new IntFormat("wave.waiting", i -> { + ibuild.setLength(0); + int m = i/60; + int s = i % 60; + if(m <= 0){ + ibuild.append(s); + }else{ + ibuild.append(m); + ibuild.append(":"); + if(s < 10){ + ibuild.append("0"); + } + ibuild.append(s); + } + return ibuild.toString(); + }); table.clearChildren(); table.touchable(Touchable.enabled); diff --git a/core/src/io/anuke/mindustry/ui/fragments/LoadingFragment.java b/core/src/io/anuke/mindustry/ui/fragments/LoadingFragment.java index 18876d0e08..c994102e68 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/LoadingFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/LoadingFragment.java @@ -18,11 +18,11 @@ public class LoadingFragment extends Fragment{ t.touchable(Touchable.enabled); t.add().height(70f).row(); - t.addImage("white").growX().height(3f).pad(4f).growX().get().setColor(Pal.accent); + t.addImage("whiteui").growX().height(3f).pad(4f).growX().get().setColor(Pal.accent); t.row(); t.add("$loading").name("namelabel").pad(10f); t.row(); - t.addImage("white").growX().height(3f).pad(4f).growX().get().setColor(Pal.accent); + t.addImage("whiteui").growX().height(3f).pad(4f).growX().get().setColor(Pal.accent); t.row(); button = t.addButton("$cancel", () -> { diff --git a/core/src/io/anuke/mindustry/ui/fragments/MenuFragment.java b/core/src/io/anuke/mindustry/ui/fragments/MenuFragment.java index 1ef2d52494..6a6352b916 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/MenuFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/MenuFragment.java @@ -2,30 +2,59 @@ package io.anuke.mindustry.ui.fragments; import io.anuke.arc.Core; import io.anuke.arc.Events; +import io.anuke.arc.graphics.Color; +import io.anuke.arc.graphics.Texture; +import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.arc.math.Interpolation; import io.anuke.arc.scene.Group; -import io.anuke.arc.scene.ui.layout.Table; -import io.anuke.arc.util.Strings; -import io.anuke.mindustry.core.GameState.State; +import io.anuke.arc.scene.actions.Actions; +import io.anuke.arc.scene.event.Touchable; +import io.anuke.arc.scene.ui.Button; +import io.anuke.arc.scene.ui.layout.*; +import io.anuke.arc.util.Align; import io.anuke.mindustry.core.Platform; +import io.anuke.mindustry.game.EventType.DisposeEvent; import io.anuke.mindustry.game.EventType.ResizeEvent; import io.anuke.mindustry.game.Version; -import io.anuke.mindustry.ui.MenuButton; +import io.anuke.mindustry.graphics.MenuRenderer; import io.anuke.mindustry.ui.MobileButton; -import io.anuke.mindustry.ui.dialogs.FloatingDialog; import static io.anuke.mindustry.Vars.*; public class MenuFragment extends Fragment{ - private Table container; + private Texture logo = new Texture("sprites/logo.png"); + private Table container, submenu; + private Button currentMenu; + private MenuRenderer renderer; + + public MenuFragment(){ + Events.on(DisposeEvent.class, event -> { + renderer.dispose(); + logo.dispose(); + }); + } @Override public void build(Group parent){ + renderer = new MenuRenderer(); + + Group group = new WidgetGroup(); + group.setFillParent(true); + group.visible(() -> !ui.editor.isShown()); + parent.addChild(group); + + parent = group; + + parent.fill((x, y, w, h) -> { + renderer.render(); + }); + parent.fill(c -> { container = c; - container.visible(() -> state.is(State.menu)); if(!mobile){ buildDesktop(); + Events.on(ResizeEvent.class, event -> buildDesktop()); }else{ buildMobile(); Events.on(ResizeEvent.class, event -> buildMobile()); @@ -33,19 +62,29 @@ public class MenuFragment extends Fragment{ }); //discord icon in top right - parent.fill(c -> c.top().right().addButton("", "discord", ui.discord::show).size(84, 45) - .visible(() -> state.is(State.menu))); + //parent.fill(c -> c.top().right().addButton("", "discord", ui.discord::show).size(84, 45) + //.visible(() -> state.is(State.menu))); //info icon if(mobile){ - parent.fill(c -> c.top().left().addButton("", "info", ui.about::show).size(84, 45) - .visible(() -> state.is(State.menu))); + parent.fill(c -> c.bottom().left().addButton("", "info", ui.about::show).size(84, 45)); } - //version info - 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))); + String versionText = "[#ffffffba]" + ((Version.build == -1) ? "[#fc8140aa]custom build" : Version.modifier + " build " + Version.build); + + parent.fill((x, y, w, h) -> { + float logoscl = (int)Unit.dp.scl(1); + float logow = Math.min(logo.getWidth() * logoscl, Core.graphics.getWidth() - Unit.dp.scl(20)); + float logoh = logow * (float)logo.getHeight() / logo.getWidth(); + + float fx = (int)(Core.graphics.getWidth() / 2f); + float fy = (int)(Core.graphics.getHeight() - 6 - logoh) + logoh / 2 - (Core.graphics.isPortrait() ? Unit.dp.scl(30f) : 0f); + + Draw.color(); + Draw.rect(Draw.wrap(logo), fx, fy, logow, logoh); + Core.scene.skin.font().setColor(Color.WHITE); + Core.scene.skin.font().draw(versionText, fx, fy - logoh/2f, Align.center); + }).touchable(Touchable.disabled); } private void buildMobile(){ @@ -53,20 +92,21 @@ public class MenuFragment extends Fragment{ container.setSize(Core.graphics.getWidth(), Core.graphics.getHeight()); float size = 120f; - float isize = 14f * 4; + float isize = iconsize; container.defaults().size(size).pad(5).padTop(4f); MobileButton - play = new MobileButton("icon-play-2", isize, "$play", ui.deploy::show), - maps = new MobileButton("icon-map", isize, "$maps", ui.maps::show), - custom = new MobileButton("icon-play-custom", isize, "$customgame", this::showCustomSelect), - join = new MobileButton("icon-add", isize, "$joingame", ui.join::show), - editor = new MobileButton("icon-editor", isize, "$editor", () -> ui.loadAnd(ui.editor::show)), - tools = new MobileButton("icon-tools", isize, "$settings", ui.settings::show), - donate = new MobileButton("icon-donate", isize, "$donate", () -> Core.net.openURI(donationURL)), - exit = new MobileButton("icon-exit", isize, "$quit", () -> Core.app.exit()); + play = new MobileButton("icon-play-2", isize, "$campaign", ui.deploy::show), + custom = new MobileButton("icon-play-custom", isize, "$customgame", ui.custom::show), + maps = new MobileButton("icon-load", isize, "$loadgame", ui.load::show), + join = new MobileButton("icon-add", isize, "$joingame", ui.join::show), + editor = new MobileButton("icon-editor", isize, "$editor", ui.maps::show), + tools = new MobileButton("icon-tools", isize, "$settings", ui.settings::show), + donate = new MobileButton("icon-donate", isize, "$donate", () -> Core.net.openURI(donationURL)), + exit = new MobileButton("icon-exit", isize, "$quit", () -> Core.app.exit()); if(!Core.graphics.isPortrait()){ + container.marginTop(60f); container.add(play); container.add(join); container.add(custom); @@ -83,6 +123,7 @@ public class MenuFragment extends Fragment{ table.add(exit); }).colspan(4); }else{ + container.marginTop(0f); container.add(play); container.add(maps); container.row(); @@ -97,60 +138,111 @@ public class MenuFragment extends Fragment{ table.defaults().set(container.defaults()); if(Platform.instance.canDonate()) table.add(donate); - table.add(exit); + if(!ios) table.add(exit); }).colspan(2); } } private void buildDesktop(){ - container.table(out -> { + container.clear(); + container.setSize(Core.graphics.getWidth(), Core.graphics.getHeight()); - float w = 200f; - float bw = w * 2f + 10f; - out.margin(16); - out.defaults().size(w, 66f).padTop(5).padRight(5); + float width = 230f; + String background = "flat-trans"; - out.add(new MenuButton("icon-play-2", "$play", ui.deploy::show)).width(bw).colspan(2); + container.left(); + container.add().width(Core.graphics.getWidth()/10f); + container.table(background, t -> { + t.defaults().width(width).height(70f); - out.row(); + buttons(t, + new Buttoni("$play", "icon-play-2", + new Buttoni("$campaign", "icon-play-2", ui.deploy::show), + new Buttoni("$joingame", "icon-add", ui.join::show), + new Buttoni("$customgame", "icon-editor", ui.custom::show), + new Buttoni("$loadgame", "icon-load", ui.load::show) + ), + new Buttoni("$editor", "icon-editor", ui.maps::show), + new Buttoni("$settings", "icon-tools", ui.settings::show), + new Buttoni("$about.button", "icon-info", ui.about::show), + new Buttoni("$quit", "icon-exit", Core.app::exit) + ); - out.add(new MenuButton("icon-add", "$joingame", ui.join::show)); + }).width(width).growY(); - out.add(new MenuButton("icon-play-custom", "$customgame", this::showCustomSelect)); + container.table(background, t -> { + submenu = t; + t.getColor().a = 0f; + t.top(); + t.defaults().width(width).height(70f); + t.visible(() -> !t.getChildren().isEmpty()); - out.row(); - - out.add(new MenuButton("icon-editor", "$editor", () -> ui.loadAnd(ui.editor::show))); - - out.add(new MenuButton("icon-map", "$maps", ui.maps::show)); - - out.row(); - - out.add(new MenuButton("icon-info", "$about.button", ui.about::show)); - - out.add(new MenuButton("icon-tools", "$settings", ui.settings::show)); - - out.row(); - - out.add(new MenuButton("icon-exit", "$quit", Core.app::exit)).width(bw).colspan(2); - }); + }).width(width).growY(); } - private void showCustomSelect(){ - FloatingDialog dialog = new FloatingDialog("$play"); - dialog.setFillParent(false); - dialog.addCloseButton(); - dialog.cont.defaults().size(210f, 64f); - dialog.cont.add(new MenuButton("icon-editor", "$newgame", () -> { - dialog.hide(); - ui.custom.show(); - })); - dialog.cont.row(); - dialog.cont.add(new MenuButton("icon-load", "$loadgame", () -> { - ui.load.show(); - dialog.hide(); - })); - dialog.show(); + private void fadeInMenu(){ + submenu.clearActions(); + submenu.actions(Actions.alpha(1f, 0.15f, Interpolation.fade)); + } + + private void fadeOutMenu(){ + //nothing to fade out + if(submenu.getChildren().isEmpty()){ + return; + } + + submenu.clearActions(); + submenu.actions(Actions.alpha(1f), Actions.alpha(0f, 0.2f, Interpolation.fade), Actions.run(() -> submenu.clearChildren())); + } + + private void buttons(Table t, Buttoni... buttons){ + for(Buttoni b : buttons){ + Button[] out = {null}; + out[0] = t.addImageTextButton(b.text, b.icon + "-small", "clear-toggle-menu", + iconsizesmall, () -> { + if(currentMenu == out[0]){ + currentMenu = null; + fadeOutMenu(); + }else{ + if(b.submenu != null){ + currentMenu = out[0]; + submenu.clearChildren(); + fadeInMenu(); + //correctly offset the button + submenu.add().height((Core.graphics.getHeight() - out[0].getY(Align.topLeft)) / Unit.dp.scl(1f)); + submenu.row(); + buttons(submenu, b.submenu); + }else{ + currentMenu = null; + fadeOutMenu(); + b.runnable.run(); + } + } + }).marginLeft(11f).get(); + out[0].update(() -> out[0].setChecked(currentMenu == out[0])); + t.row(); + } + } + + private class Buttoni{ + final String icon; + final String text; + final Runnable runnable; + final Buttoni[] submenu; + + public Buttoni(String text, String icon, Runnable runnable){ + this.icon = icon; + this.text = text; + this.runnable = runnable; + this.submenu = null; + } + + public Buttoni(String text, String icon, Buttoni... buttons){ + this.icon = icon; + this.text = text; + this.runnable = () -> {}; + this.submenu = buttons; + } } } diff --git a/core/src/io/anuke/mindustry/ui/fragments/OverlayFragment.java b/core/src/io/anuke/mindustry/ui/fragments/OverlayFragment.java index c7fd119393..c2e3ccd086 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/OverlayFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/OverlayFragment.java @@ -1,16 +1,18 @@ package io.anuke.mindustry.ui.fragments; import io.anuke.arc.scene.Group; -import io.anuke.mindustry.input.InputHandler; +import io.anuke.arc.scene.event.Touchable; +import io.anuke.arc.scene.ui.layout.WidgetGroup; /** Fragment for displaying overlays such as block inventories. */ public class OverlayFragment extends Fragment{ public final BlockInventoryFragment inv; public final BlockConfigFragment config; - private Group group = new Group(); + private WidgetGroup group = new WidgetGroup(); - public OverlayFragment(InputHandler input){ + public OverlayFragment(){ + group.touchable(Touchable.childrenOnly); inv = new BlockInventoryFragment(); config = new BlockConfigFragment(); } diff --git a/core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java b/core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java index 29e5d9cd90..a54f6c7039 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/PlacementFragment.java @@ -11,7 +11,7 @@ import io.anuke.arc.scene.event.Touchable; import io.anuke.arc.scene.style.TextureRegionDrawable; import io.anuke.arc.scene.ui.*; import io.anuke.arc.scene.ui.layout.Table; -import io.anuke.mindustry.core.GameState.State; +import io.anuke.mindustry.content.Blocks; import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.game.EventType.UnlockEvent; import io.anuke.mindustry.game.EventType.WorldLoadEvent; @@ -53,8 +53,10 @@ public class PlacementFragment extends Fragment{ public PlacementFragment(){ Events.on(WorldLoadEvent.class, event -> { - control.input().block = null; - rebuild(); + Core.app.post(() -> { + control.input().block = null; + rebuild(); + }); }); Events.on(UnlockEvent.class, event -> { @@ -115,7 +117,7 @@ public class PlacementFragment extends Fragment{ public void build(Group parent){ parent.fill(full -> { toggler = full; - full.bottom().right().visible(() -> !state.is(State.menu) && ui.hudfrag.shown()); + full.bottom().right().visible(() -> ui.hudfrag.shown()); full.table(frame -> { InputHandler input = control.input(); @@ -142,7 +144,7 @@ public class PlacementFragment extends Fragment{ ImageButton button = blockTable.addImageButton("icon-locked", "select", 8 * 4, () -> { if(unlocked(block)){ - input.block = block; + input.block = input.block == block ? null : block; } }).size(46f).group(group).get(); @@ -150,7 +152,8 @@ public class PlacementFragment extends Fragment{ button.update(() -> { //color unplacable things gray TileEntity core = player.getClosestCore(); - Color color = state.rules.infiniteResources || (core != null && (core.items.has(block.buildRequirements, state.rules.buildCostMultiplier) || state.rules.infiniteResources)) ? Color.WHITE : Color.GRAY; + Color color = block.buildVisibility == Blocks.padVisible && !block.buildVisibility.get() ? Pal.noplace : + state.rules.infiniteResources || (core != null && (core.items.has(block.buildRequirements, state.rules.buildCostMultiplier) || state.rules.infiniteResources)) ? Color.WHITE : Color.GRAY; button.forEach(elem -> elem.setColor(color)); button.setChecked(input.block == block); }); @@ -162,6 +165,12 @@ public class PlacementFragment extends Fragment{ } }); } + //add missing elements to even out table size + if(index < 4){ + for(int i = 0; i < 4-index; i++){ + blockTable.add().size(46f); + } + } blockTable.act(0f); }; @@ -194,6 +203,10 @@ public class PlacementFragment extends Fragment{ header.addButton("?", "clear-partial", () -> ui.content.show(lastDisplay)) .size(8 * 5).padTop(-5).padRight(-5).right().grow(); } + if(lastDisplay.buildVisibility == Blocks.padVisible && !lastDisplay.buildVisibility.get()){ + header.row(); + header.add("$attackpvponly").width(230f).wrap().colspan(3).left(); + } }).growX().left(); topTable.row(); //add requirement table @@ -238,7 +251,7 @@ public class PlacementFragment extends Fragment{ }); }).colspan(3).fillX().visible(() -> getSelected() != null || tileDisplayBlock() != null).touchable(Touchable.enabled); frame.row(); - frame.addImage("blank").color(Pal.accent).colspan(3).height(3).growX(); + frame.addImage("whiteui").color(Pal.gray).colspan(3).height(4).growX(); frame.row(); frame.table("pane-2", blocksSelect -> { blocksSelect.margin(4).marginTop(0); @@ -262,11 +275,11 @@ public class PlacementFragment extends Fragment{ if(f++ % 2 == 0) categories.row(); if(categoryEmpty[cat.ordinal()]){ - categories.addImage("flat"); + categories.addImage("flat-trans"); continue; } - categories.addImageButton("icon-" + cat.name(), "clear-toggle", 16 * 2, () -> { + categories.addImageButton("icon-" + cat.name() + "-med", "clear-toggle-trans", iconsizemed, () -> { currentCategory = cat; rebuildCategory.run(); }).group(group).update(i -> i.setChecked(currentCategory == cat)); @@ -291,7 +304,7 @@ public class PlacementFragment extends Fragment{ Array getByCategory(Category cat){ returnArray.clear(); for(Block block : content.blocks()){ - if(block.buildCategory == cat && block.isVisible()){ + if(block.buildCategory == cat && (block.isVisible() || block.buildVisibility == Blocks.padVisible)){ returnArray.add(block); } } @@ -336,6 +349,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.overlay().itemDrop != null ? hoverTile.overlay() : null; + return hoverTile == null ? null : hoverTile.block().synthetic() ? hoverTile.block() : hoverTile.drop() != null ? hoverTile.overlay().itemDrop != null ? hoverTile.overlay() : hoverTile.floor() : null; } } \ No newline at end of file diff --git a/core/src/io/anuke/mindustry/ui/fragments/PlayerListFragment.java b/core/src/io/anuke/mindustry/ui/fragments/PlayerListFragment.java index 09b19a889c..058ceaba08 100644 --- a/core/src/io/anuke/mindustry/ui/fragments/PlayerListFragment.java +++ b/core/src/io/anuke/mindustry/ui/fragments/PlayerListFragment.java @@ -9,6 +9,7 @@ import io.anuke.arc.scene.ui.Image; import io.anuke.arc.scene.ui.layout.Table; import io.anuke.arc.scene.ui.layout.Unit; import io.anuke.arc.util.Interval; +import io.anuke.arc.util.Scaling; import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.graphics.Pal; @@ -81,21 +82,21 @@ public class PlayerListFragment extends Fragment{ @Override public void draw(){ super.draw(); - Draw.color(Pal.accent); + Draw.color(Pal.gray); Draw.alpha(parentAlpha); - Lines.stroke(Unit.dp.scl(3f)); + Lines.stroke(Unit.dp.scl(4f)); Lines.rect(x, y, width, height); Draw.reset(); } }; table.margin(8); - table.add(new Image(user.mech.iconRegion)).grow(); + table.add(new Image(user.mech.getContentIcon()).setScaling(Scaling.none)).grow(); button.add(table).size(h); button.labelWrap("[#" + user.color.toString().toUpperCase() + "]" + user.name).width(170f).pad(10); button.add().grow(); - button.addImage("icon-admin").size(14 * 2).visible(() -> user.isAdmin && !(!user.isLocal && Net.server())).padRight(5).get().updateVisibility(); + button.addImage("icon-admin").size(iconsize).visible(() -> user.isAdmin && !(!user.isLocal && Net.server())).padRight(5).get().updateVisibility(); if((Net.server() || player.isAdmin) && !user.isLocal && (!user.isAdmin || Net.server())){ button.add().growY(); @@ -105,14 +106,14 @@ public class PlayerListFragment extends Fragment{ button.table(t -> { t.defaults().size(bs); - t.addImageButton("icon-ban", "clear-partial", 14 * 2, + t.addImageButton("icon-ban-small", "clear-partial", iconsizesmall, () -> ui.showConfirm("$confirm", "$confirmban", () -> Call.onAdminRequest(user, AdminAction.ban))); - t.addImageButton("icon-cancel", "clear-partial", 16 * 2, + t.addImageButton("icon-cancel-small", "clear-partial", iconsizesmall, () -> ui.showConfirm("$confirm", "$confirmkick", () -> Call.onAdminRequest(user, AdminAction.kick))); t.row(); - t.addImageButton("icon-admin", "clear-toggle-partial", 14 * 2, () -> { + t.addImageButton("icon-admin-small", "clear-toggle-partial", iconsizesmall, () -> { if(Net.client()) return; String id = user.uuid; @@ -128,14 +129,14 @@ public class PlayerListFragment extends Fragment{ .touchable(() -> Net.client() ? Touchable.disabled : Touchable.enabled) .checked(user.isAdmin); - t.addImageButton("icon-zoom-small", "clear-partial", 14 * 2, () -> Call.onAdminRequest(user, AdminAction.trace)); + t.addImageButton("icon-zoom-small", "clear-partial", iconsizesmall, () -> Call.onAdminRequest(user, AdminAction.trace)); }).padRight(12).size(bs + 10f, bs); } content.add(button).padBottom(-6).width(350f).maxHeight(h + 14); content.row(); - content.addImage("blank").height(3f).color(state.rules.pvp ? user.getTeam().color : Pal.accent).growX(); + content.addImage("whiteui").height(4f).color(state.rules.pvp ? user.getTeam().color : Pal.gray).growX(); content.row(); }); diff --git a/core/src/io/anuke/mindustry/world/Block.java b/core/src/io/anuke/mindustry/world/Block.java index 76fa59c63d..b8a50b8243 100644 --- a/core/src/io/anuke/mindustry/world/Block.java +++ b/core/src/io/anuke/mindustry/world/Block.java @@ -27,6 +27,8 @@ import io.anuke.mindustry.input.InputHandler.PlaceDraw; import io.anuke.mindustry.type.*; import io.anuke.mindustry.ui.Bar; import io.anuke.mindustry.ui.ContentDisplay; +import io.anuke.mindustry.world.blocks.Floor; +import io.anuke.mindustry.world.blocks.OverlayFloor; import io.anuke.mindustry.world.consumers.*; import io.anuke.mindustry.world.meta.*; @@ -37,6 +39,8 @@ import static io.anuke.mindustry.Vars.*; public class Block extends BlockStorage{ public static final int crackRegions = 8, maxCrackSize = 5; + private static final BooleanProvider invisible = () -> false; + /** whether this block has a tile entity that updates */ public boolean update; /** whether this block has health and can be destroyed */ @@ -102,7 +106,7 @@ public class Block extends BlockStorage{ /** Cost of building this block; do not modify directly! */ public float buildCost; /** Whether this block is visible and can currently be built. */ - public BooleanProvider buildVisibility = () -> false; + public BooleanProvider buildVisibility = invisible; /** Whether this block has instant transfer.*/ public boolean instantTransfer = false; public boolean alwaysUnlocked = false; @@ -133,6 +137,10 @@ public class Block extends BlockStorage{ return true; } + public boolean isBuildable(){ + return buildVisibility != invisible; + } + public void onProximityRemoved(Tile tile){ if(tile.entity.power != null){ tile.block().powerGraphRemoved(tile); @@ -299,7 +307,7 @@ public class Block extends BlockStorage{ @Override public TextureRegion getContentIcon(){ - return icon(Icon.large); + return icon(Icon.medium); } @Override @@ -345,7 +353,7 @@ public class Block extends BlockStorage{ cacheRegions[i] = Core.atlas.find(cacheRegionStrings.get(i)); } - if(cracks == null || cracks[0][0].getTexture().isDisposed()){ + if(cracks == null || (cracks[0][0].getTexture() != null && cracks[0][0].getTexture().isDisposed())){ cracks = new TextureRegion[maxCrackSize][crackRegions]; for(int size = 1; size <= maxCrackSize; size++){ for(int i = 0; i < crackRegions; i++){ @@ -589,7 +597,8 @@ public class Block extends BlockStorage{ public TextureRegion icon(Icon icon){ if(icons[icon.ordinal()] == null){ - icons[icon.ordinal()] = Core.atlas.find(name + "-icon-" + icon.name(), icon == Icon.full ? getGeneratedIcons()[0] : Core.atlas.find(name + "-icon-full", getGeneratedIcons()[0])); + icons[icon.ordinal()] = Core.atlas.find(name + "-icon-" + icon.name(), icon == Icon.full ? + getGeneratedIcons()[0] : Core.atlas.find(name + "-icon-full", getGeneratedIcons()[0])); } return icons[icon.ordinal()]; } @@ -658,6 +667,18 @@ public class Block extends BlockStorage{ return buildVisibility.get() && !isHidden(); } + public boolean isFloor(){ + return this instanceof Floor; + } + + public boolean isOverlay(){ + return this instanceof OverlayFloor; + } + + public Floor asFloor(){ + return (Floor)this; + } + @Override public boolean isHidden(){ return !buildVisibility.get(); @@ -687,10 +708,11 @@ public class Block extends BlockStorage{ } public enum Icon{ + //these are stored in the UI atlases small(8 * 3), medium(8 * 4), large(8 * 6), - /** uses whatever the size of the block is */ + /** uses whatever the size of the block is. this is always stored in the main game atlas! */ full(0); public final int size; diff --git a/core/src/io/anuke/mindustry/world/StaticTree.java b/core/src/io/anuke/mindustry/world/StaticTree.java new file mode 100644 index 0000000000..be6b6c4c76 --- /dev/null +++ b/core/src/io/anuke/mindustry/world/StaticTree.java @@ -0,0 +1,44 @@ +package io.anuke.mindustry.world; + +import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.arc.graphics.g2d.TextureRegion; +import io.anuke.arc.util.Tmp; +import io.anuke.mindustry.world.blocks.StaticWall; + +import static io.anuke.mindustry.Vars.tilesize; + +public class StaticTree extends StaticWall{ + + public StaticTree(String name){ + super(name); + } + + @Override + public void draw(Tile tile){ + TextureRegion r = Tmp.tr1; + r.set(region); + int crop = (region.getWidth() - tilesize*4) / 2; + float ox = 0; + float oy = 0; + + for(int i = 0; i < 4; i++){ + if(tile.getNearby(i) != null && tile.getNearby(i).block() instanceof StaticWall){ + + if(i == 0){ + r.setWidth(r.getWidth() - crop); + ox -= crop /2f; + }else if(i == 1){ + r.setY(r.getY() + crop); + oy -= crop /2f; + }else if(i == 2){ + r.setX(r.getX() + crop); + ox += crop /2f; + }else{ + r.setHeight(r.getHeight() - crop); + oy += crop /2f; + } + } + } + Draw.rect(r, tile.drawx() + ox * Draw.scl, tile.drawy() + oy * Draw.scl); + } +} diff --git a/core/src/io/anuke/mindustry/world/Tile.java b/core/src/io/anuke/mindustry/world/Tile.java index cac7d27a7f..f46178f1d4 100644 --- a/core/src/io/anuke/mindustry/world/Tile.java +++ b/core/src/io/anuke/mindustry/world/Tile.java @@ -1,16 +1,15 @@ package io.anuke.mindustry.world; -import io.anuke.arc.collection.Array; -import io.anuke.arc.function.Consumer; -import io.anuke.arc.math.Mathf; +import io.anuke.arc.collection.*; +import io.anuke.arc.function.*; +import io.anuke.arc.math.*; import io.anuke.arc.math.geom.*; -import io.anuke.mindustry.content.Blocks; -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.content.*; +import io.anuke.mindustry.entities.traits.*; +import io.anuke.mindustry.entities.type.*; +import io.anuke.mindustry.game.*; +import io.anuke.mindustry.type.*; +import io.anuke.mindustry.world.blocks.*; import io.anuke.mindustry.world.modules.*; import static io.anuke.mindustry.Vars.*; @@ -23,25 +22,24 @@ public class Tile implements Position, TargetTrait{ public short x, y; protected Block block; protected Floor floor; + protected Floor overlay; /** Rotation, 0-3. Also used to store offload location, in which case it can be any number.*/ protected byte rotation; /** Team ordinal. */ protected byte team; - /** Ore that is on top of this (floor) block. */ - protected short overlay = 0; public Tile(int x, int y){ this.x = (short)x; this.y = (short)y; - block = floor = (Floor)Blocks.air; + block = floor = overlay = (Floor)Blocks.air; } public Tile(int x, int y, int floor, int overlay, int wall){ this.x = (short)x; this.y = (short)y; this.floor = (Floor)content.block(floor); + this.overlay = (Floor)content.block(overlay); this.block = content.block(wall); - this.overlay = (short)overlay; //update entity and create it if needed changed(); @@ -115,7 +113,7 @@ public class Tile implements Position, TargetTrait{ } public Floor overlay(){ - return (Floor)content.block(overlay); + return overlay; } @SuppressWarnings("unchecked") @@ -158,7 +156,14 @@ public class Tile implements Position, TargetTrait{ /**This resets the overlay!*/ public void setFloor(Floor type){ this.floor = type; - this.overlay = 0; + this.overlay = (Floor)Blocks.air; + } + + /** Sets the floor, preserving overlay.*/ + public void setFloorUnder(Floor floor){ + Block overlay = this.overlay; + setFloor(floor); + setOverlay(overlay); } public byte rotation(){ @@ -170,7 +175,7 @@ public class Tile implements Position, TargetTrait{ } public short overlayID(){ - return overlay; + return overlay.id; } public short blockID(){ @@ -182,15 +187,15 @@ public class Tile implements Position, TargetTrait{ } public void setOverlayID(short ore){ - this.overlay = ore; + this.overlay = (Floor)content.block(ore); } public void setOverlay(Block block){ - setOverlayID(block.id); + this.overlay = (Floor)block; } public void clearOverlay(){ - this.overlay = 0; + setOverlayID((short)0); } public boolean passable(){ @@ -273,20 +278,6 @@ public class Tile implements Position, TargetTrait{ return tmpArray; } - /** Returns the block the multiblock is linked to, or null if it is not linked to any block. - public Tile getLinked(){ - if(!isLinked()){ - return null; - }else{ - return world.tile(x + linkX(rotation), y + linkY(rotation)); - } - } - - public Tile target(){ - Tile link = getLinked(); - return link == null ? this : link; - }*/ - public Rectangle getHitbox(Rectangle rect){ return rect.setSize(block().size * tilesize).setCenter(drawx(), drawy()); } @@ -312,7 +303,7 @@ public class Tile implements Position, TargetTrait{ } public Item drop(){ - return overlay == 0 || ((Floor)content.block(overlay)).itemDrop == null ? floor.itemDrop : ((Floor)content.block(overlay)).itemDrop; + return overlay == Blocks.air || overlay.itemDrop == null ? floor.itemDrop : overlay.itemDrop; } public void updateOcclusion(){ @@ -340,7 +331,7 @@ public class Tile implements Position, TargetTrait{ //+26 - if(link().synthetic()){ + if(link().synthetic() && link().solid()){ cost += Mathf.clamp(link().block.health / 10f, 0, 20); } @@ -439,6 +430,6 @@ public class Tile implements Position, TargetTrait{ @Override public String toString(){ - return floor.name + ":" + block.name + ":" + content.block(overlay) + "[" + x + "," + y + "] " + "entity=" + (entity == null ? "null" : (entity.getClass())) + ":" + getTeam(); + return floor.name + ":" + block.name + ":" + overlay + "[" + x + "," + y + "] " + "entity=" + (entity == null ? "null" : (entity.getClass())) + ":" + getTeam(); } } \ No newline at end of file diff --git a/core/src/io/anuke/mindustry/world/blocks/BuildBlock.java b/core/src/io/anuke/mindustry/world/blocks/BuildBlock.java index e1205b465e..a896f8583b 100644 --- a/core/src/io/anuke/mindustry/world/blocks/BuildBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/BuildBlock.java @@ -170,7 +170,7 @@ public class BuildBlock extends Block{ * The recipe of the block that is being constructed. * If there is no recipe for this block, as is the case with rocks, 'previous' is used. */ - public Block cblock; + public @Nullable Block cblock; public float progress = 0; public float buildCost; @@ -220,14 +220,17 @@ public class BuildBlock extends Block{ setDeconstruct(previous); } + //make sure you take into account that you can't deconstruct more than there is deconstructed + float clampedAmount = Math.min(amount, progress); + for(int i = 0; i < requirements.length; i++){ int reqamount = Math.round(state.rules.buildCostMultiplier * requirements[i].amount); - accumulator[i] += Math.min(amount * deconstructMultiplier * reqamount, deconstructMultiplier * reqamount - totalAccumulator[i]); //add scaled amount progressed to the accumulator - totalAccumulator[i] = Math.min(totalAccumulator[i] + reqamount * amount * deconstructMultiplier, reqamount); + accumulator[i] += Math.min(clampedAmount * deconstructMultiplier * reqamount, deconstructMultiplier * reqamount - totalAccumulator[i]); //add scaled amount progressed to the accumulator + totalAccumulator[i] = Math.min(totalAccumulator[i] + reqamount * clampedAmount * deconstructMultiplier, reqamount); int accumulated = (int)(accumulator[i]); //get amount - if(amount > 0 && accumulated > 0){ //if it's positive, add it to the core + if(clampedAmount > 0 && accumulated > 0){ //if it's positive, add it to the core if(core != null){ int accepting = core.tile.block().acceptStack(requirements[i].item, accumulated, core.tile, builder); core.tile.block().handleStack(requirements[i].item, accepting, core.tile, builder); diff --git a/core/src/io/anuke/mindustry/world/blocks/DoubleOverlayFloor.java b/core/src/io/anuke/mindustry/world/blocks/DoubleOverlayFloor.java new file mode 100644 index 0000000000..7a0a26847d --- /dev/null +++ b/core/src/io/anuke/mindustry/world/blocks/DoubleOverlayFloor.java @@ -0,0 +1,20 @@ +package io.anuke.mindustry.world.blocks; + +import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.arc.math.Mathf; +import io.anuke.mindustry.world.Tile; + +public class DoubleOverlayFloor extends OverlayFloor{ + + public DoubleOverlayFloor(String name){ + super(name); + } + + @Override + public void draw(Tile tile){ + Draw.colorl(0.4f); + Draw.rect(variantRegions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, variantRegions.length - 1))], tile.worldx(), tile.worldy() - 0.75f); + Draw.color(); + Draw.rect(variantRegions[Mathf.randomSeed(tile.pos(), 0, Math.max(0, variantRegions.length - 1))], tile.worldx(), tile.worldy()); + } +} diff --git a/core/src/io/anuke/mindustry/world/blocks/ItemSelection.java b/core/src/io/anuke/mindustry/world/blocks/ItemSelection.java index 2515f58ec8..4c9fbeab91 100644 --- a/core/src/io/anuke/mindustry/world/blocks/ItemSelection.java +++ b/core/src/io/anuke/mindustry/world/blocks/ItemSelection.java @@ -28,7 +28,7 @@ public class ItemSelection{ for(Item item : items){ if(!data.isUnlocked(item) && world.isZone()) continue; - ImageButton button = cont.addImageButton("white", "clear-toggle", 24, () -> control.input().frag.config.hideConfig()).group(group).get(); + ImageButton button = cont.addImageButton("whiteui", "clear-toggle-trans", 24, () -> control.input().frag.config.hideConfig()).group(group).get(); button.changed(() -> consumer.accept(button.isChecked() ? item : null)); button.getStyle().imageUp = new TextureRegionDrawable(item.icon(Icon.medium)); button.update(() -> button.setChecked(holder.get() == item)); diff --git a/core/src/io/anuke/mindustry/world/blocks/StaticWall.java b/core/src/io/anuke/mindustry/world/blocks/StaticWall.java index b645abb3b5..79a9b6f1d7 100644 --- a/core/src/io/anuke/mindustry/world/blocks/StaticWall.java +++ b/core/src/io/anuke/mindustry/world/blocks/StaticWall.java @@ -1,15 +1,12 @@ package io.anuke.mindustry.world.blocks; import io.anuke.arc.Core; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.graphics.g2d.TextureRegion; +import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.math.Mathf; import io.anuke.mindustry.graphics.CacheLayer; -import io.anuke.mindustry.world.Pos; -import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.*; -import static io.anuke.mindustry.Vars.tilesize; -import static io.anuke.mindustry.Vars.world; +import static io.anuke.mindustry.Vars.*; public class StaticWall extends Rock{ TextureRegion large; diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/DeflectorWall.java b/core/src/io/anuke/mindustry/world/blocks/defense/DeflectorWall.java index 1d0822d14f..9730320239 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/DeflectorWall.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/DeflectorWall.java @@ -2,7 +2,7 @@ package io.anuke.mindustry.world.blocks.defense; import io.anuke.arc.graphics.Blending; import io.anuke.arc.graphics.Color; -import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.*; import io.anuke.arc.util.Time; @@ -35,7 +35,7 @@ public class DeflectorWall extends Wall{ Draw.color(Color.WHITE); Draw.alpha(entity.hit * 0.5f); Draw.blend(Blending.additive); - Draw.rect("blank", tile.drawx(), tile.drawy(), tilesize * size, tilesize * size); + Fill.rect(tile.drawx(), tile.drawy(), tilesize * size, tilesize * size); Draw.blend(); Draw.reset(); diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/Door.java b/core/src/io/anuke/mindustry/world/blocks/defense/Door.java index 04da951cff..34a855dae8 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/Door.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/Door.java @@ -1,17 +1,16 @@ package io.anuke.mindustry.world.blocks.defense; +import io.anuke.annotations.Annotations.*; import io.anuke.arc.Core; import io.anuke.arc.Graphics.Cursor; import io.anuke.arc.Graphics.Cursor.SystemCursor; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.graphics.g2d.TextureRegion; +import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.math.geom.Rectangle; import io.anuke.mindustry.content.Fx; -import io.anuke.mindustry.entities.Effects; +import io.anuke.mindustry.entities.*; import io.anuke.mindustry.entities.Effects.Effect; -import io.anuke.mindustry.entities.Units; -import io.anuke.mindustry.entities.type.Player; -import io.anuke.mindustry.entities.type.TileEntity; +import io.anuke.mindustry.entities.type.*; +import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.world.Tile; import java.io.*; @@ -33,6 +32,22 @@ public class Door extends Wall{ consumesTap = true; } + @Remote(called = Loc.server) + public static void onDoorToggle(Player player, Tile tile, boolean open){ + DoorEntity entity = tile.entity(); + if(entity != null){ + entity.open = open; + Door door = (Door)tile.block(); + + world.pathfinder.updateSolid(tile); + if(!entity.open){ + Effects.effect(door.openfx, tile.drawx(), tile.drawy()); + }else{ + Effects.effect(door.closefx, tile.drawx(), tile.drawy()); + } + } + } + @Override public void load(){ super.load(); @@ -69,13 +84,7 @@ public class Door extends Wall{ return; } - entity.open = !entity.open; - world.pathfinder.updateSolid(tile); - if(!entity.open){ - Effects.effect(closefx, tile.drawx(), tile.drawy()); - }else{ - Effects.effect(openfx, tile.drawx(), tile.drawy()); - } + Call.onDoorToggle(null, tile, !entity.open); } @Override diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/MendProjector.java b/core/src/io/anuke/mindustry/world/blocks/defense/MendProjector.java index 2afb132878..887762ba9b 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/MendProjector.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/MendProjector.java @@ -2,25 +2,20 @@ package io.anuke.mindustry.world.blocks.defense; import io.anuke.arc.Core; import io.anuke.arc.collection.IntSet; -import io.anuke.arc.graphics.Blending; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.math.Mathf; -import io.anuke.arc.util.Time; -import io.anuke.arc.util.Tmp; +import io.anuke.arc.util.*; import io.anuke.mindustry.content.Fx; import io.anuke.mindustry.entities.Effects; import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.graphics.Pal; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.meta.BlockStat; -import io.anuke.mindustry.world.meta.StatUnit; +import io.anuke.mindustry.world.*; +import io.anuke.mindustry.world.meta.*; import java.io.*; -import static io.anuke.mindustry.Vars.tilesize; -import static io.anuke.mindustry.Vars.world; +import static io.anuke.mindustry.Vars.*; public class MendProjector extends Block{ private static Color color = Color.valueOf("84f491"); @@ -130,13 +125,13 @@ public class MendProjector extends Block{ Draw.color(color, phase, entity.phaseHeat); Draw.alpha(entity.heat * Mathf.absin(Time.time(), 10f, 1f) * 0.5f); - Draw.blend(Blending.additive); + //Draw.blend(Blending.additive); Draw.rect(topRegion, tile.drawx(), tile.drawy()); - Draw.blend(); + //Draw.blend(); Draw.alpha(1f); Lines.stroke((2f * f + 0.2f) * entity.heat); - Lines.circle(tile.drawx(), tile.drawy(), ((1f - f) * 8f) * size / 2f); + Lines.square(tile.drawx(), tile.drawy(), ((1f - f) * 8f) * size / 2f); Draw.reset(); } diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/OverdriveProjector.java b/core/src/io/anuke/mindustry/world/blocks/defense/OverdriveProjector.java index 711a45dc74..956560ddf2 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/OverdriveProjector.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/OverdriveProjector.java @@ -2,22 +2,18 @@ package io.anuke.mindustry.world.blocks.defense; import io.anuke.arc.Core; import io.anuke.arc.collection.IntSet; -import io.anuke.arc.graphics.Blending; import io.anuke.arc.graphics.Color; import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Time; import io.anuke.mindustry.entities.type.TileEntity; import io.anuke.mindustry.graphics.Pal; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.Tile; -import io.anuke.mindustry.world.meta.BlockStat; -import io.anuke.mindustry.world.meta.StatUnit; +import io.anuke.mindustry.world.*; +import io.anuke.mindustry.world.meta.*; import java.io.*; -import static io.anuke.mindustry.Vars.tilesize; -import static io.anuke.mindustry.Vars.world; +import static io.anuke.mindustry.Vars.*; public class OverdriveProjector extends Block{ private static Color color = Color.valueOf("feb380"); @@ -102,8 +98,10 @@ public class OverdriveProjector extends Block{ if(other == null) continue; if(other.getTeamID() == tile.getTeamID() && !healed.contains(other.pos()) && other.entity != null){ - other.entity.timeScaleDuration = Math.max(other.entity.timeScaleDuration, reload + 1f); - other.entity.timeScale = Math.max(other.entity.timeScale, realBoost); + if(other.entity.timeScale <= realBoost){ + other.entity.timeScaleDuration = Math.max(other.entity.timeScaleDuration, reload + 1f); + other.entity.timeScale = Math.max(other.entity.timeScale, realBoost); + } healed.add(other.pos()); } } @@ -130,12 +128,12 @@ public class OverdriveProjector extends Block{ Draw.color(color, phase, entity.phaseHeat); Draw.alpha(entity.heat * Mathf.absin(Time.time(), 10f, 1f) * 0.5f); - Draw.blend(Blending.additive); + //Draw.blend(Blending.additive); Draw.rect(topRegion, tile.drawx(), tile.drawy()); - Draw.blend(); + //Draw.blend(); Draw.alpha(1f); Lines.stroke((2f * f + 0.2f) * entity.heat); - Lines.circle(tile.drawx(), tile.drawy(), (1f - f) * 9f); + Lines.square(tile.drawx(), tile.drawy(), (1f - f) * 8f); Draw.reset(); } @@ -164,4 +162,4 @@ public class OverdriveProjector extends Block{ phaseHeat = stream.readFloat(); } } -} \ No newline at end of file +} diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/LaserTurret.java b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/LaserTurret.java index f619d1727f..e7196e2140 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/LaserTurret.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/LaserTurret.java @@ -11,6 +11,7 @@ import io.anuke.mindustry.type.Liquid; import io.anuke.mindustry.world.Tile; import io.anuke.mindustry.world.consumers.*; import io.anuke.mindustry.world.meta.BlockStat; +import io.anuke.mindustry.world.meta.StatUnit; import static io.anuke.mindustry.Vars.tilesize; @@ -30,6 +31,9 @@ public class LaserTurret extends PowerTurret{ super.setStats(); stats.remove(BlockStat.boostEffect); + stats.remove(BlockStat.damage); + //damages every 5 ticks, at least in meltdown's case + stats.add(BlockStat.damage, shootType.damage * 60f / 5f, StatUnit.perSecond); } @Override diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/PowerTurret.java b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/PowerTurret.java index 1c11cd3da2..b8b0055096 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/PowerTurret.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/PowerTurret.java @@ -2,6 +2,8 @@ package io.anuke.mindustry.world.blocks.defense.turrets; import io.anuke.mindustry.entities.bullet.BulletType; import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.meta.BlockStat; +import io.anuke.mindustry.world.meta.StatUnit; public abstract class PowerTurret extends CooledTurret{ protected BulletType shootType; @@ -12,6 +14,13 @@ public abstract class PowerTurret extends CooledTurret{ hasPower = true; } + @Override + public void setStats(){ + super.setStats(); + + stats.add(BlockStat.damage, shootType.damage, StatUnit.none); + } + @Override public void init(){ consumes.powerCond(powerUse, entity -> ((TurretEntity)entity).target != null); diff --git a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/Turret.java b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/Turret.java index 52d0cba905..77ec838ba6 100644 --- a/core/src/io/anuke/mindustry/world/blocks/defense/turrets/Turret.java +++ b/core/src/io/anuke/mindustry/world/blocks/defense/turrets/Turret.java @@ -193,7 +193,11 @@ public abstract class Turret extends Block{ protected void findTarget(Tile tile){ TurretEntity entity = tile.entity(); - entity.target = Units.closestTarget(tile.getTeam(), tile.drawx(), tile.drawy(), range, e -> !e.isDead() && (!e.isFlying() || targetAir) && (e.isFlying() || targetGround)); + if(targetAir && !targetGround){ + entity.target = Units.closestEnemy(tile.getTeam(), tile.drawx(), tile.drawy(), range, e -> !e.isDead() && e.isFlying()); + }else{ + entity.target = Units.closestTarget(tile.getTeam(), tile.drawx(), tile.drawy(), range, e -> !e.isDead() && (!e.isFlying() || targetAir) && (e.isFlying() || targetGround)); + } } protected void turnToTarget(Tile tile, float targetRot){ diff --git a/core/src/io/anuke/mindustry/world/blocks/distribution/Conduit.java b/core/src/io/anuke/mindustry/world/blocks/distribution/Conduit.java index e4b4bc1950..6064d6483d 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/Conduit.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/Conduit.java @@ -40,7 +40,7 @@ public class Conduit extends LiquidBlock{ ConduitEntity entity = tile.entity(); entity.blendbits = 0; - entity.blendshadowrot = -1; + entity.blendrot = 0; if(blends(tile, 2) && blends(tile, 1) && blends(tile, 3)){ entity.blendbits = 3; @@ -52,10 +52,8 @@ public class Conduit extends LiquidBlock{ entity.blendbits = 4; }else if(blends(tile, 1)){ entity.blendbits = 5; - entity.blendshadowrot = 0; }else if(blends(tile, 3)){ entity.blendbits = 1; - entity.blendshadowrot = 1; } } @@ -116,6 +114,6 @@ public class Conduit extends LiquidBlock{ public float smoothLiquid; byte blendbits; - int blendshadowrot; + int blendrot; } } 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 22ca19a48a..f5a86d0d1d 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/ItemBridge.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/ItemBridge.java @@ -113,7 +113,8 @@ public class ItemBridge extends Block{ float w = (link.x == x ? tilesize : Math.abs(link.x - x) * tilesize - tilesize); float h = (link.y == y ? tilesize : Math.abs(link.y - y) * tilesize - tilesize); Lines.rect((x + link.x) / 2f * tilesize - w / 2f, (y + link.y) / 2f * tilesize - h / 2f, w, h); - Fill.poly(link.x * tilesize + Geometry.d4[rot].x * tilesize, link.y * tilesize + Geometry.d4[rot].y * tilesize, 3, 2.8f, link.absoluteRelativeTo(x, y) * 90); + + Draw.rect("bridge-arrow", link.x * tilesize + Geometry.d4[rot].x * tilesize, link.y * tilesize + Geometry.d4[rot].y * tilesize, link.absoluteRelativeTo(x, y) * 90); } Draw.reset(); } 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 f04e47cb4e..73657741da 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/MassDriver.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/MassDriver.java @@ -204,7 +204,7 @@ public class MassDriver extends Block{ if(entity.link == other.pos()){ Call.linkMassDriver(null, tile, -1); return false; - }else if(other.block() instanceof MassDriver && other.dst(tile) <= range){ + }else if(other.block() instanceof MassDriver && other.dst(tile) <= range && other.getTeam() == tile.getTeam()){ Call.linkMassDriver(null, tile, other.pos()); return false; } diff --git a/core/src/io/anuke/mindustry/world/blocks/distribution/Sorter.java b/core/src/io/anuke/mindustry/world/blocks/distribution/Sorter.java index 210f09d3d3..a7497079f4 100644 --- a/core/src/io/anuke/mindustry/world/blocks/distribution/Sorter.java +++ b/core/src/io/anuke/mindustry/world/blocks/distribution/Sorter.java @@ -2,7 +2,7 @@ package io.anuke.mindustry.world.blocks.distribution; import io.anuke.annotations.Annotations.*; import io.anuke.arc.Core; -import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.math.Mathf; import io.anuke.arc.scene.ui.layout.Table; import io.anuke.mindustry.entities.type.*; @@ -54,7 +54,7 @@ public class Sorter extends Block{ if(entity.sortItem == null) return; Draw.color(entity.sortItem.color); - Draw.rect("blank", tile.worldx(), tile.worldy(), 4f, 4f); + Draw.rect("center", tile.worldx(), tile.worldy()); Draw.color(); } 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 e3d04259c6..95881ec265 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/ImpactReactor.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/ImpactReactor.java @@ -31,8 +31,7 @@ public class ImpactReactor extends PowerGenerator{ protected int explosionDamage = 2000; protected Color plasma1 = Color.valueOf("ffd06b"), plasma2 = Color.valueOf("ff361b"); - protected Color ind1 = Color.valueOf("858585"), ind2 = Color.valueOf("fea080"); - protected int bottomRegion, topRegion, lightRegion; + protected int bottomRegion; protected int[] plasmaRegions; public ImpactReactor(String name){ @@ -44,8 +43,6 @@ public class ImpactReactor extends PowerGenerator{ outputsPower = consumesPower = true; bottomRegion = reg("-bottom"); - topRegion = reg("-top"); - lightRegion = reg("-light"); plasmaRegions = new int[plasmas]; for(int i = 0; i < plasmas; i++){ plasmaRegions[i] = reg("-plasma-" + i); @@ -82,7 +79,7 @@ public class ImpactReactor extends PowerGenerator{ entity.warmup = 1f; } - if(entity.timer.get(timerUse, itemDuration)){ + if(entity.timer.get(timerUse, itemDuration / entity.timeScale)){ entity.cons.trigger(); } }else{ @@ -112,17 +109,12 @@ public class ImpactReactor extends PowerGenerator{ Draw.rect(region, tile.drawx(), tile.drawy()); - Draw.rect(reg(topRegion), tile.drawx(), tile.drawy()); - - Draw.color(ind1, ind2, entity.warmup + Mathf.absin(entity.productionEfficiency, 3f, entity.warmup * 0.5f)); - Draw.rect(reg(lightRegion), tile.drawx(), tile.drawy()); - Draw.color(); } @Override public TextureRegion[] generateIcons(){ - return new TextureRegion[]{Core.atlas.find(name + "-bottom"), Core.atlas.find(name), Core.atlas.find(name + "-top")}; + return new TextureRegion[]{Core.atlas.find(name + "-bottom"), Core.atlas.find(name)}; } @Override diff --git a/core/src/io/anuke/mindustry/world/blocks/power/ItemLiquidGenerator.java b/core/src/io/anuke/mindustry/world/blocks/power/ItemLiquidGenerator.java index 9088a19e3d..a57f165907 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/ItemLiquidGenerator.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/ItemLiquidGenerator.java @@ -36,7 +36,7 @@ public class ItemLiquidGenerator extends PowerGenerator{ protected Effects.Effect generateEffect = Fx.generatespark; protected Effects.Effect explodeEffect = Fx.generatespark; protected Color heatColor = Color.valueOf("ff9b59"); - protected TextureRegion topRegion; + protected TextureRegion topRegion, liquidRegion; protected boolean randomlyExplode = false; public ItemLiquidGenerator(boolean hasItems, boolean hasLiquids, String name){ @@ -59,6 +59,7 @@ public class ItemLiquidGenerator extends PowerGenerator{ if(hasItems){ topRegion = Core.atlas.find(name + "-top"); } + liquidRegion = Core.atlas.find(name + "-liquid"); } @Override @@ -151,15 +152,11 @@ public class ItemLiquidGenerator extends PowerGenerator{ if(hasLiquids){ Draw.color(entity.liquids.current().color); Draw.alpha(entity.liquids.currentAmount() / liquidCapacity); - drawLiquidCenter(tile); + Draw.rect(liquidRegion, tile.drawx(), tile.drawy()); Draw.color(); } } - public void drawLiquidCenter(Tile tile){ - Draw.rect("blank", tile.drawx(), tile.drawy(), 2, 2); - } - protected float getItemEfficiency(Item item){ return 0.0f; } diff --git a/core/src/io/anuke/mindustry/world/blocks/power/NuclearReactor.java b/core/src/io/anuke/mindustry/world/blocks/power/NuclearReactor.java index bde3b43176..4938d96e3c 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/NuclearReactor.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/NuclearReactor.java @@ -2,8 +2,7 @@ package io.anuke.mindustry.world.blocks.power; import io.anuke.arc.Core; import io.anuke.arc.graphics.Color; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.graphics.g2d.TextureRegion; +import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Vector2; import io.anuke.arc.util.Time; @@ -86,7 +85,7 @@ public class NuclearReactor extends PowerGenerator{ if(fuel > 0){ entity.heat += fullness * heating * Math.min(entity.delta(), 4f); - if(entity.timer.get(timerFuel, itemDuration)){ + if(entity.timer.get(timerFuel, itemDuration / entity.timeScale)){ entity.cons.trigger(); } } @@ -155,7 +154,7 @@ public class NuclearReactor extends PowerGenerator{ NuclearReactorEntity entity = tile.entity(); Draw.color(coolColor, hotColor, entity.heat); - Draw.rect("white", tile.drawx(), tile.drawy(), size * tilesize, size * tilesize); + Fill.rect(tile.drawx(), tile.drawy(), size * tilesize, size * tilesize); Draw.color(entity.liquids.current().color); Draw.alpha(entity.liquids.currentAmount() / liquidCapacity); 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 d8ac8b05d9..a2c1410a50 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/PowerGraph.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/PowerGraph.java @@ -40,6 +40,7 @@ public class PowerGraph{ public float getPowerProduced(){ float powerProduced = 0f; for(Tile producer : producers){ + if(producer.entity == null) continue; powerProduced += producer.block().getPowerProduction(producer) * producer.entity.delta(); } return powerProduced; @@ -148,6 +149,13 @@ public class PowerGraph{ public void update(){ if(Core.graphics.getFrameId() == lastFrameUpdated){ + return; + }else if(!consumers.isEmpty() && consumers.first().isEnemyCheat()){ + //when cheating, just set satisfaction to 1 + for(Tile tile : consumers){ + tile.entity.power.satisfaction = 1f; + } + return; } @@ -180,11 +188,6 @@ public class PowerGraph{ } public void add(Tile tile){ - if(tile.block().consumes.hasPower() && !tile.block().consumes.getPower().buffered){ - //reset satisfaction to zero in case of direct consumer. There is no reason to clear power from buffered consumers. - tile.entity.power.satisfaction = 0.0f; - } - tile.entity.power.graph = this; all.add(tile); diff --git a/core/src/io/anuke/mindustry/world/blocks/power/PowerNode.java b/core/src/io/anuke/mindustry/world/blocks/power/PowerNode.java index af73a01302..03b23b0568 100644 --- a/core/src/io/anuke/mindustry/world/blocks/power/PowerNode.java +++ b/core/src/io/anuke/mindustry/world/blocks/power/PowerNode.java @@ -4,8 +4,7 @@ import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; import io.anuke.arc.Core; 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.*; import io.anuke.arc.math.Angles; import io.anuke.arc.math.Mathf; import io.anuke.arc.math.geom.Intersector; @@ -28,8 +27,8 @@ public class PowerNode extends PowerBlock{ //last distribution block placed private static int lastPlaced = -1; - protected Vector2 t1 = new Vector2(); - protected Vector2 t2 = new Vector2(); + protected Vector2 t1 = new Vector2(), t2 = new Vector2(); + protected TextureRegion laser, laserEnd; protected float laserRange = 6; protected int maxNodes = 3; @@ -86,6 +85,14 @@ public class PowerNode extends PowerBlock{ } } + @Override + public void load(){ + super.load(); + + laser = Core.atlas.find("laser"); + laserEnd = Core.atlas.find("laser-end"); + } + @Override public void setBars(){ super.setBars(); @@ -204,7 +211,7 @@ public class PowerNode extends PowerBlock{ for(int i = 0; i < entity.power.links.size; i++){ Tile link = world.tile(entity.power.links.get(i)); - if(linkValid(tile, link)){ + if(linkValid(tile, link) && (link.pos() < tile.pos() || !(link.block() instanceof PowerNode) || !Core.camera.bounds(Tmp.r1).contains(link.drawx(), link.drawy()))){ drawLaser(tile, link); } } @@ -237,15 +244,12 @@ public class PowerNode extends PowerBlock{ } protected void drawLaser(Tile tile, Tile target){ - float x1 = tile.drawx(), y1 = tile.drawy(), x2 = target.drawx(), y2 = target.drawy(); float angle1 = Angles.angle(x1, y1, x2, y2); - float angle2 = angle1 + 180f; - t1.trns(angle1, tile.block().size * tilesize / 2f - 1.5f); - t2.trns(angle2, target.block().size * tilesize / 2f - 1.5f); + t2.trns(angle1 + 180f, target.block().size * tilesize / 2f - 1.5f); x1 += t1.x; y1 += t1.y; @@ -253,10 +257,8 @@ public class PowerNode extends PowerBlock{ y2 += t2.y; Draw.color(Pal.powerLight, Color.WHITE, Mathf.absin(Time.time(), 8f, 0.3f) + 0.2f); - //Lines.stroke(2f); - //Lines.line(x1, y1, x2, y2); - - Shapes.laser("laser", "laser-end", x1, y1, x2, y2, 0.6f); + Shapes.laser(laser, laserEnd, x1, y1, x2, y2, 0.6f); + Draw.color(); } } 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 6cce3928d7..2aa7c7fe49 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/Drill.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/Drill.java @@ -5,8 +5,7 @@ import io.anuke.arc.collection.Array; import io.anuke.arc.collection.ObjectIntMap; import io.anuke.arc.graphics.Blending; import io.anuke.arc.graphics.Color; -import io.anuke.arc.graphics.g2d.Draw; -import io.anuke.arc.graphics.g2d.TextureRegion; +import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.math.Mathf; import io.anuke.arc.util.Strings; import io.anuke.arc.util.Time; @@ -116,7 +115,7 @@ public class Drill extends Block{ if(entity.dominantItem != null && drawMineItem){ Draw.color(entity.dominantItem.color); - Draw.rect("blank", tile.drawx(), tile.drawy(), 2f, 2f); + Fill.square(tile.drawx(), tile.drawy(), 1f); Draw.color(); } } diff --git a/core/src/io/anuke/mindustry/world/blocks/production/Fracker.java b/core/src/io/anuke/mindustry/world/blocks/production/Fracker.java index a792a1c334..6f0051c999 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/Fracker.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/Fracker.java @@ -39,6 +39,11 @@ public class Fracker extends SolidPump{ @Override public void drawCracks(Tile tile){} + @Override + public boolean canProduce(Tile tile){ + return tile.entity.liquids.get(result) < liquidCapacity; + } + @Override public void draw(Tile tile){ FrackerEntity entity = tile.entity(); diff --git a/core/src/io/anuke/mindustry/world/blocks/production/Separator.java b/core/src/io/anuke/mindustry/world/blocks/production/Separator.java index e29f2fe218..37199f6c61 100644 --- a/core/src/io/anuke/mindustry/world/blocks/production/Separator.java +++ b/core/src/io/anuke/mindustry/world/blocks/production/Separator.java @@ -57,7 +57,11 @@ public class Separator extends Block{ })); stats.add(BlockStat.productionTime, craftTime / 60f, StatUnit.seconds); + } + @Override + public boolean canProduce(Tile tile){ + return tile.entity.items.total() < itemCapacity; } @Override 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 c84e772533..19c7bb2779 100644 --- a/core/src/io/anuke/mindustry/world/blocks/sandbox/LiquidSource.java +++ b/core/src/io/anuke/mindustry/world/blocks/sandbox/LiquidSource.java @@ -83,7 +83,7 @@ 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, () -> control.input().frag.config.hideConfig()).size(38).group(group).get(); + ImageButton button = cont.addImageButton("clear", "clear-toggle-trans", 24, () -> control.input().frag.config.hideConfig()).size(38).group(group).get(); button.changed(() -> { Call.setLiquidSourceLiquid(null, tile, button.isChecked() ? items.get(f) : null); control.input().frag.config.hideConfig(); diff --git a/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java b/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java index 9d85168575..f081b7c98c 100644 --- a/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java +++ b/core/src/io/anuke/mindustry/world/blocks/storage/CoreBlock.java @@ -2,7 +2,6 @@ package io.anuke.mindustry.world.blocks.storage; import io.anuke.annotations.Annotations.Loc; import io.anuke.annotations.Annotations.Remote; -import io.anuke.arc.Core; import io.anuke.arc.collection.EnumSet; import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.math.Mathf; @@ -24,7 +23,6 @@ import io.anuke.mindustry.world.meta.BlockFlag; import static io.anuke.mindustry.Vars.*; public class CoreBlock extends StorageBlock{ - protected TextureRegion topRegion; public CoreBlock(String name){ super(name); @@ -83,23 +81,17 @@ public class CoreBlock extends StorageBlock{ state.teams.get(tile.getTeam()).cores.add(tile); } - @Override - public void load(){ - super.load(); - - topRegion = Core.atlas.find(name + "-top"); - } - @Override public void draw(Tile tile){ CoreEntity entity = tile.entity(); Draw.rect(region, tile.drawx(), tile.drawy()); - if(Core.atlas.isFound(topRegion)){ - Draw.alpha(entity.heat); - Draw.rect(topRegion, tile.drawx(), tile.drawy()); - Draw.color(); + if(entity.heat > 0){ + Draw.color(Pal.darkMetal); + Lines.stroke(2f * entity.heat); + Lines.poly(tile.drawx(), tile.drawy(), 4, 8f * entity.heat); + Draw.reset(); } if(entity.currentUnit != null){ 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 ce784a3b7a..2d237a3f39 100644 --- a/core/src/io/anuke/mindustry/world/blocks/storage/Unloader.java +++ b/core/src/io/anuke/mindustry/world/blocks/storage/Unloader.java @@ -1,17 +1,14 @@ package io.anuke.mindustry.world.blocks.storage; -import io.anuke.annotations.Annotations.Loc; -import io.anuke.annotations.Annotations.Remote; +import io.anuke.annotations.Annotations.*; import io.anuke.arc.Core; import io.anuke.arc.graphics.Color; -import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.arc.graphics.g2d.*; import io.anuke.arc.scene.ui.layout.Table; -import io.anuke.mindustry.entities.type.Player; -import io.anuke.mindustry.entities.type.TileEntity; +import io.anuke.mindustry.entities.type.*; import io.anuke.mindustry.gen.Call; import io.anuke.mindustry.type.Item; -import io.anuke.mindustry.world.Block; -import io.anuke.mindustry.world.Tile; +import io.anuke.mindustry.world.*; import io.anuke.mindustry.world.blocks.ItemSelection; import java.io.*; @@ -81,7 +78,7 @@ public class Unloader extends Block{ SortedUnloaderEntity entity = tile.entity(); Draw.color(entity.sortItem == null ? Color.CLEAR : entity.sortItem.color); - Draw.rect("blank", tile.worldx(), tile.worldy(), 2f, 2f); + Fill.square(tile.worldx(), tile.worldy(), 1f); Draw.color(); } diff --git a/core/src/io/anuke/mindustry/world/blocks/units/RepairPoint.java b/core/src/io/anuke/mindustry/world/blocks/units/RepairPoint.java index 7eb2b6b40f..a1fae03e22 100644 --- a/core/src/io/anuke/mindustry/world/blocks/units/RepairPoint.java +++ b/core/src/io/anuke/mindustry/world/blocks/units/RepairPoint.java @@ -25,6 +25,7 @@ public class RepairPoint extends Block{ protected float repairSpeed = 0.3f; protected float powerUse; protected TextureRegion baseRegion; + protected TextureRegion laser, laserEnd; public RepairPoint(String name){ super(name); @@ -32,7 +33,7 @@ public class RepairPoint extends Block{ solid = true; flags = EnumSet.of(BlockFlag.repair); layer = Layer.turret; - layer2 = Layer.laser; + layer2 = Layer.power; hasPower = true; outlineIcon = true; } @@ -42,6 +43,8 @@ public class RepairPoint extends Block{ super.load(); baseRegion = Core.atlas.find(name + "-base"); + laser = Core.atlas.find("laser"); + laserEnd = Core.atlas.find("laser-end"); } @Override @@ -79,9 +82,9 @@ public class RepairPoint extends Block{ float len = 5f; Draw.color(Color.valueOf("e8ffd7")); - Shapes.laser("laser", "laser-end", - tile.drawx() + Angles.trnsx(ang, len), tile.drawy() + Angles.trnsy(ang, len), - entity.target.x, entity.target.y, entity.strength); + Shapes.laser(laser, laserEnd, + tile.drawx() + Angles.trnsx(ang, len), tile.drawy() + Angles.trnsy(ang, len), + entity.target.x, entity.target.y, entity.strength); 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 7e4a6d483d..39e7fbae19 100644 --- a/core/src/io/anuke/mindustry/world/blocks/units/UnitFactory.java +++ b/core/src/io/anuke/mindustry/world/blocks/units/UnitFactory.java @@ -127,7 +127,7 @@ public class UnitFactory extends Block{ Shaders.build.progress = entity.buildTime / produceTime; Shaders.build.color.set(Pal.accent); Shaders.build.color.a = entity.speedScl; - Shaders.build.time = -entity.time / 10f; + Shaders.build.time = -entity.time / 20f; Draw.shader(Shaders.build); Draw.rect(region, tile.drawx(), tile.drawy()); @@ -137,7 +137,7 @@ public class UnitFactory extends Block{ Draw.alpha(entity.speedScl); Lines.lineAngleCenter( - tile.drawx() + Mathf.sin(entity.time, 6f, Vars.tilesize / 2f * size - 2f), + tile.drawx() + Mathf.sin(entity.time, 20f, Vars.tilesize / 2f * size - 2f), tile.drawy(), 90, size * Vars.tilesize - 4f); diff --git a/core/src/io/anuke/mindustry/world/consumers/ConsumeLiquid.java b/core/src/io/anuke/mindustry/world/consumers/ConsumeLiquid.java index 9cc8eba1fb..943e7da6b2 100644 --- a/core/src/io/anuke/mindustry/world/consumers/ConsumeLiquid.java +++ b/core/src/io/anuke/mindustry/world/consumers/ConsumeLiquid.java @@ -28,7 +28,7 @@ public class ConsumeLiquid extends ConsumeLiquidBase{ @Override public String getIcon(){ - return "icon-liquid-small"; + return "icon-liquid-consume"; } @Override diff --git a/core/src/io/anuke/mindustry/world/consumers/ConsumeLiquidFilter.java b/core/src/io/anuke/mindustry/world/consumers/ConsumeLiquidFilter.java index 6da77814e8..04c2efd3ae 100644 --- a/core/src/io/anuke/mindustry/world/consumers/ConsumeLiquidFilter.java +++ b/core/src/io/anuke/mindustry/world/consumers/ConsumeLiquidFilter.java @@ -38,7 +38,7 @@ public class ConsumeLiquidFilter extends ConsumeLiquidBase{ @Override public String getIcon(){ - return "icon-liquid-small"; + return "icon-liquid-consume"; } @Override diff --git a/core/src/io/anuke/mindustry/world/consumers/ConsumePower.java b/core/src/io/anuke/mindustry/world/consumers/ConsumePower.java index 1df63e61e1..18b2d422db 100644 --- a/core/src/io/anuke/mindustry/world/consumers/ConsumePower.java +++ b/core/src/io/anuke/mindustry/world/consumers/ConsumePower.java @@ -32,7 +32,7 @@ public class ConsumePower extends Consume{ @Override public String getIcon(){ - return "icon-power-small"; + return "icon-power"; } @Override diff --git a/core/src/io/anuke/mindustry/world/meta/BlockStat.java b/core/src/io/anuke/mindustry/world/meta/BlockStat.java index 364f0cd3c3..4845e4936e 100644 --- a/core/src/io/anuke/mindustry/world/meta/BlockStat.java +++ b/core/src/io/anuke/mindustry/world/meta/BlockStat.java @@ -39,6 +39,7 @@ public enum BlockStat{ powerShot(StatCategory.shooting), targetsAir(StatCategory.shooting), targetsGround(StatCategory.shooting), + damage(StatCategory.shooting), ammo(StatCategory.shooting), booster(StatCategory.optional), diff --git a/core/src/io/anuke/mindustry/world/modules/ConsumeModule.java b/core/src/io/anuke/mindustry/world/modules/ConsumeModule.java index c7a3c09b17..e4a08ec413 100644 --- a/core/src/io/anuke/mindustry/world/modules/ConsumeModule.java +++ b/core/src/io/anuke/mindustry/world/modules/ConsumeModule.java @@ -14,6 +14,12 @@ public class ConsumeModule extends BlockModule{ } public void update(){ + //everything is valid here + if(entity.tile.isEnemyCheat()){ + valid = optionalValid = true; + return; + } + boolean prevValid = valid(); valid = true; optionalValid = true; diff --git a/desktop-sdl/build.gradle b/desktop-sdl/build.gradle new file mode 100644 index 0000000000..2b15ccc5ca --- /dev/null +++ b/desktop-sdl/build.gradle @@ -0,0 +1,86 @@ +apply plugin: "java" + +sourceCompatibility = 1.8 +sourceSets.main.java.srcDirs = [ "src/" ] + +project.ext.mainClassName = "io.anuke.mindustry.desktopsdl.DesktopLauncher" +project.ext.assetsDir = new File("../core/assets") + +def IKVM_DIR = System.env.IKVM_HOME +def getTarget = { return project.hasProperty("target") ? project.properties["target"] : "windows" } + +task run(dependsOn: classes, type: JavaExec) { + main = project.mainClassName + classpath = sourceSets.main.runtimeClasspath + standardInput = System.in + workingDir = project.assetsDir + ignoreExitValue = true + + if(System.getProperty("os.name").toLowerCase().contains("mac")){ + jvmArgs("-XstartOnFirstThread", "-Djava.awt.headless=true") + } + + if(project.hasProperty("args")){ + args Eval.me(project.getProperties()["args"]) + } + + if(args.contains("debug")){ + main = "io.anuke.mindustry.DebugLauncher" + } +} + +task dist(type: Jar, dependsOn: classes) { + from files(sourceSets.main.output.classesDirs) + from files(sourceSets.main.output.resourcesDir) + from {configurations.compile.collect {zipTree(it)}} + from files(project.assetsDir); + + //use target = all for all platforms + def target = getTarget() + if(target == "windows") exclude('**.so', "**.dylib") + if(target == "mac") exclude('**.so', "**.dll") + if(target == "linux") exclude('**.dll', "**.dylib") + archivesBaseName = appName + "-" + target + + manifest { + attributes 'Main-Class': project.mainClassName + } +} + +task ikZip(type: Zip){ + def filename = "$appName-windows-${version}" + + from "build/libs/$filename" + archiveBaseName = "$appName-${getTarget()}" +} + +task ikdist{ + dependsOn dist + finalizedBy ikZip + + doLast{ + def filename = "$appName-windows-${version}" + def folder = "build/libs/$filename" + def args = ["mono", "$IKVM_DIR/ikvmc.exe", "-target:winexe", "-static", "-out:build/libs/${filename}.exe", "build/libs/${filename}.jar"] + if(file("../core/assets/sprites/icon.ico").exists()){ + args += ["-win32icon:../core/assets/sprites/icon.ico"] + }else if(file("../core/assets/icons/icon.ico").exists()){ + args += ["-win32icon:../core/assets/icons/icon.ico"] + } + + exec{ + commandLine args + } + + copy{ + from file("build/libs/${filename}.exe") + into file(folder) + } + + copy{ + from "$IKVM_DIR/libraries" + into folder + } + } +} + diff --git a/desktop-sdl/src/io/anuke/mindustry/desktopsdl/DesktopLauncher.java b/desktop-sdl/src/io/anuke/mindustry/desktopsdl/DesktopLauncher.java new file mode 100644 index 0000000000..fd7ed3edfd --- /dev/null +++ b/desktop-sdl/src/io/anuke/mindustry/desktopsdl/DesktopLauncher.java @@ -0,0 +1,30 @@ +package io.anuke.mindustry.desktopsdl; +import io.anuke.arc.Files.*; +import io.anuke.arc.backends.sdl.*; +import io.anuke.mindustry.Mindustry; +import io.anuke.mindustry.core.Platform; +import io.anuke.mindustry.net.*; + +public class DesktopLauncher{ + + public static void main(String[] arg){ + try{ + + Platform.instance = new DesktopPlatform(arg); + + Net.setClientProvider(new ArcNetClient()); + Net.setServerProvider(new ArcNetServer()); + new SdlApplication(new Mindustry(), new SdlConfig(){{ + title = "Mindustry"; + maximized = true; + depth = 0; + stencil = 0; + width = 900; + height = 700; + setWindowIcon(FileType.Internal, "icons/icon.png"); + }}); + }catch(Throwable e){ + DesktopPlatform.handleCrash(e); + } + } +} diff --git a/desktop-sdl/src/io/anuke/mindustry/desktopsdl/DesktopPlatform.java b/desktop-sdl/src/io/anuke/mindustry/desktopsdl/DesktopPlatform.java new file mode 100644 index 0000000000..5bf16aab0c --- /dev/null +++ b/desktop-sdl/src/io/anuke/mindustry/desktopsdl/DesktopPlatform.java @@ -0,0 +1,138 @@ +package io.anuke.mindustry.desktopsdl; + +import club.minnced.discord.rpc.*; +import io.anuke.arc.collection.*; +import io.anuke.arc.files.*; +import io.anuke.arc.function.*; +import io.anuke.arc.util.*; +import io.anuke.arc.util.serialization.*; +import io.anuke.mindustry.core.GameState.*; +import io.anuke.mindustry.core.*; +import io.anuke.mindustry.net.*; +import io.anuke.mindustry.ui.dialogs.*; +import sdl.*; + +import java.net.*; +import java.util.*; + +import static io.anuke.mindustry.Vars.*; + +public class DesktopPlatform extends Platform{ + static boolean useDiscord = OS.is64Bit; + final static String applicationId = "398246104468291591"; + String[] args; + + public DesktopPlatform(String[] args){ + this.args = args; + + testMobile = Array.with(args).contains("-testMobile"); + + if(useDiscord){ + try{ + DiscordEventHandlers handlers = new DiscordEventHandlers(); + DiscordRPC.INSTANCE.Discord_Initialize(applicationId, handlers, true, ""); + + Runtime.getRuntime().addShutdownHook(new Thread(DiscordRPC.INSTANCE::Discord_Shutdown)); + }catch(Throwable t){ + useDiscord = false; + Log.err("Failed to initialize discord.", t); + } + } + } + + static void handleCrash(Throwable e){ + Consumer dialog = r -> new Thread(r).start(); + boolean badGPU = false; + + if(e.getMessage() != null && (e.getMessage().contains("Couldn't create window") || e.getMessage().contains("OpenGL 2.0 or higher"))){ + + dialog.accept(() -> message( + e.getMessage().contains("Couldn't create window") ? "A graphics initialization error has occured! Try to update your graphics drivers:\n" + e.getMessage() : + "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.)")); + badGPU = true; + } + + boolean fbgp = badGPU; + + CrashSender.send(e, file -> { + if(!fbgp){ + dialog.accept(() -> message("A crash has occured. It has been saved in:\n" + file.getAbsolutePath())); + } + }); + } + + @Override + public void showFileChooser(String text, String content, Consumer cons, boolean open, Predicate filetype){ + new FileChooser(text, file -> filetype.test(file.extension().toLowerCase()), open, cons).show(); + } + + @Override + public void updateRPC(){ + + if(!useDiscord) return; + + DiscordRichPresence presence = new DiscordRichPresence(); + + if(!state.is(State.menu)){ + presence.state = state.rules.pvp ? "PvP" : state.rules.waves ? "Survival" : "Attack"; + if(world.getMap() == null){ + presence.details = "Unknown Map"; + }else if(!state.rules.waves){ + presence.details = Strings.capitalize(world.getMap().name()); + }else{ + presence.details = Strings.capitalize(world.getMap().name()) + " | Wave " + state.wave; + presence.largeImageText = "Wave " + state.wave; + } + + if(Net.active() && playerGroup.size() > 1){ + presence.state = (state.rules.pvp ? "PvP | " : "") + playerGroup.size() + " Players"; + }else if(state.rules.waves){ + presence.state = "Survival"; + } + }else{ + if(ui.editor != null && ui.editor.isShown()){ + presence.state = "In Editor"; + }else{ + presence.state = "In Menu"; + } + } + + presence.largeImageKey = "logo"; + + DiscordRPC.INSTANCE.Discord_UpdatePresence(presence); + } + + @Override + public String getUUID(){ + try{ + Enumeration e = NetworkInterface.getNetworkInterfaces(); + NetworkInterface out; + for(out = e.nextElement(); (out.getHardwareAddress() == null || !validAddress(out.getHardwareAddress())) && e.hasMoreElements(); out = e.nextElement()); + + byte[] bytes = out.getHardwareAddress(); + byte[] result = new byte[8]; + System.arraycopy(bytes, 0, result, 0, bytes.length); + + String str = new String(Base64Coder.encode(result)); + + if(str.equals("AAAAAAAAAOA=")) throw new RuntimeException("Bad UUID."); + + return str; + }catch(Exception e){ + return super.getUUID(); + } + } + + private static void message(String message){ + SDL.SDL_ShowSimpleMessageBox(SDL.SDL_MESSAGEBOX_ERROR, "oh no", message); + } + + private boolean validAddress(byte[] bytes){ + if(bytes == null) return false; + byte[] result = new byte[8]; + System.arraycopy(bytes, 0, result, 0, bytes.length); + return !new String(Base64Coder.encode(result)).equals("AAAAAAAAAOA="); + } +} diff --git a/desktop/build.gradle b/desktop/build.gradle index 641a72cb01..97449ed185 100644 --- a/desktop/build.gradle +++ b/desktop/build.gradle @@ -6,12 +6,13 @@ sourceSets.main.java.srcDirs = ["src/"] project.ext.mainClassName = "io.anuke.mindustry.desktop.DesktopLauncher" project.ext.assetsDir = new File("../core/assets") +def IKVM_DIR = System.env.IKVM_HOME import com.badlogicgames.packr.Packr import com.badlogicgames.packr.PackrConfig def JDK_DIR = "$System.env.PACKR_DIR" -def ICON_DIR = new File("core/assets/sprites/icon.icns") +def ICON_DIR = new File("core/assets/icons/icon.icns") ext.getPlatform = { def lc = project.hasProperty("platform") ? platform.toLowerCase() : "" @@ -174,4 +175,4 @@ task packrZip(){ finalizedBy 'rzip' } -} +} \ No newline at end of file diff --git a/desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java b/desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java index 4cccab941f..289f320c0f 100644 --- a/desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java +++ b/desktop/src/io/anuke/mindustry/desktop/DesktopLauncher.java @@ -14,8 +14,8 @@ public class DesktopLauncher{ config.setTitle("Mindustry"); config.setMaximized(true); config.setBackBufferConfig(8, 8, 8, 8, 0, 0, 0); - config.setWindowedMode(960, 540); - config.setWindowIcon("sprites/icon.png"); + config.setWindowedMode(900, 600); + config.setWindowIcon("icons/icon.png"); Platform.instance = new DesktopPlatform(arg); diff --git a/desktop/src/io/anuke/mindustry/desktop/DesktopPlatform.java b/desktop/src/io/anuke/mindustry/desktop/DesktopPlatform.java index fa935f50a9..a42fd36eaf 100644 --- a/desktop/src/io/anuke/mindustry/desktop/DesktopPlatform.java +++ b/desktop/src/io/anuke/mindustry/desktop/DesktopPlatform.java @@ -15,7 +15,7 @@ import io.anuke.mindustry.ui.dialogs.FileChooser; import org.lwjgl.util.tinyfd.TinyFileDialogs; import java.net.NetworkInterface; -import java.util.Enumeration; +import java.util.*; import static io.anuke.mindustry.Vars.*; @@ -49,7 +49,7 @@ public class DesktopPlatform extends Platform{ if(e.getMessage() != null && (e.getMessage().contains("Couldn't create window") || e.getMessage().contains("OpenGL 2.0 or higher"))){ dialog.accept(() -> TinyFileDialogs.tinyfd_messageBox("oh no", - e.getMessage().contains("Couldn't create window") ? "A graphics initialization error has occured! Try to update your graphics drivers.\nReport this to the developer." : + e.getMessage().contains("Couldn't create window") ? "A graphics initialization error has occured! Try to update your graphics drivers:\n" + e.getMessage() : "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)); diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f4d7b2bf61..b0acbdcd73 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-5.5-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index cccdd3d517..383f0901c9 100755 --- a/gradlew +++ b/gradlew @@ -1,4 +1,4 @@ -#!/usr/bin/env sh +#!/usr/bin/env bash ############################################################################## ## diff --git a/ios/src/io/anuke/mindustry/IOSLauncher.java b/ios/src/io/anuke/mindustry/IOSLauncher.java index 1c01b4307d..bc1ed315a5 100644 --- a/ios/src/io/anuke/mindustry/IOSLauncher.java +++ b/ios/src/io/anuke/mindustry/IOSLauncher.java @@ -96,6 +96,7 @@ public class IOSLauncher extends IOSApplication.Delegate{ FileHandle file = Core.files.absolute(getDocumentsDirectory()).child(url.getLastPathComponent()); Core.files.absolute(url.getPath()).copyTo(file); + //TODO detect if it's a map or save if(file.extension().equalsIgnoreCase(saveExtension)){ //open save if(SaveIO.isSaveValid(file)){ diff --git a/net/src/io/anuke/mindustry/net/ArcNetClient.java b/net/src/io/anuke/mindustry/net/ArcNetClient.java index 068b47cbb6..485235724f 100644 --- a/net/src/io/anuke/mindustry/net/ArcNetClient.java +++ b/net/src/io/anuke/mindustry/net/ArcNetClient.java @@ -1,60 +1,29 @@ package io.anuke.mindustry.net; -import io.anuke.arc.Core; -import io.anuke.arc.collection.Array; -import io.anuke.arc.function.Consumer; +import io.anuke.arc.*; +import io.anuke.arc.collection.*; +import io.anuke.arc.function.*; import io.anuke.arc.net.*; -import io.anuke.arc.util.pooling.Pools; -import io.anuke.mindustry.net.Net.ClientProvider; -import io.anuke.mindustry.net.Net.SendMode; -import io.anuke.mindustry.net.Packets.Connect; -import io.anuke.mindustry.net.Packets.Disconnect; -import net.jpountz.lz4.LZ4Factory; -import net.jpountz.lz4.LZ4FastDecompressor; +import io.anuke.arc.util.pooling.*; +import io.anuke.mindustry.net.Net.*; +import io.anuke.mindustry.net.Packets.*; +import net.jpountz.lz4.*; -import java.io.IOException; +import java.io.*; import java.net.*; import java.nio.*; -import java.nio.channels.ClosedSelectorException; +import java.nio.channels.*; -import static io.anuke.mindustry.Vars.netClient; -import static io.anuke.mindustry.Vars.port; +import static io.anuke.mindustry.Vars.*; public class ArcNetClient implements ClientProvider{ final Client client; - final Array foundAddresses = new Array<>(); - final ClientDiscoveryHandler handler; + final Supplier packetSupplier = () -> new DatagramPacket(new byte[256], 256); final LZ4FastDecompressor decompressor = LZ4Factory.fastestInstance().fastDecompressor(); - Consumer lastCallback; public ArcNetClient(){ - handler = new ClientDiscoveryHandler(){ - @Override - public DatagramPacket newDatagramPacket(){ - return new DatagramPacket(new byte[256], 256); - } - - @Override - public void discoveredHost(DatagramPacket datagramPacket){ - ByteBuffer buffer = ByteBuffer.wrap(datagramPacket.getData()); - Host host = NetworkIO.readServerData(datagramPacket.getAddress().getHostAddress(), buffer); - for(InetAddress address : foundAddresses){ - if(address.equals(datagramPacket.getAddress()) || (isLocal(address) && isLocal(datagramPacket.getAddress()))){ - return; - } - } - Core.app.post(() -> lastCallback.accept(host)); - foundAddresses.add(datagramPacket.getAddress()); - } - - @Override - public void finish(){ - - } - }; - client = new Client(8192, 4096, new PacketSerializer()); - client.setDiscoveryHandler(handler); + client.setDiscoveryPacket(packetSupplier); NetListener listener = new NetListener(){ @Override @@ -172,40 +141,43 @@ public class ArcNetClient implements ClientProvider{ @Override public void pingHost(String address, int port, Consumer valid, Consumer invalid){ runAsync(() -> { - synchronized(handler){ - try{ - DatagramSocket socket = new DatagramSocket(); - socket.send(new DatagramPacket(new byte[]{-2, 1}, 2, InetAddress.getByName(address), port)); + try{ + DatagramSocket socket = new DatagramSocket(); + socket.send(new DatagramPacket(new byte[]{-2, 1}, 2, InetAddress.getByName(address), port)); + socket.setSoTimeout(2000); - socket.setSoTimeout(2000); + DatagramPacket packet = packetSupplier.get(); + socket.receive(packet); - lastCallback = valid; + ByteBuffer buffer = ByteBuffer.wrap(packet.getData()); + Host host = NetworkIO.readServerData(packet.getAddress().getHostAddress(), buffer); - DatagramPacket packet = handler.newDatagramPacket(); - - socket.receive(packet); - - ByteBuffer buffer = ByteBuffer.wrap(packet.getData()); - Host host = NetworkIO.readServerData(packet.getAddress().getHostAddress(), buffer); - - Core.app.post(() -> valid.accept(host)); - }catch(Exception e){ - Core.app.post(() -> invalid.accept(e)); - } + Core.app.post(() -> valid.accept(host)); + }catch(Exception e){ + Core.app.post(() -> invalid.accept(e)); } }); } @Override public void discover(Consumer callback, Runnable done){ - runAsync(() -> { - synchronized(handler){ - foundAddresses.clear(); - lastCallback = callback; - client.discoverHosts(port, 3000); - Core.app.post(done); - } - }); + Array foundAddresses = new Array<>(); + client.discoverHosts(port, multicastGroup, multicastPort, 3000, packet -> { + Core.app.post(() -> { + try{ + if(foundAddresses.contains(address -> address.equals(packet.getAddress()) || (isLocal(address) && isLocal(packet.getAddress())))){ + return; + } + ByteBuffer buffer = ByteBuffer.wrap(packet.getData()); + Host host = NetworkIO.readServerData(packet.getAddress().getHostAddress(), buffer); + callback.accept(host); + foundAddresses.add(packet.getAddress()); + }catch(Exception e){ + //don't crash when there's an error pinging a a server or parsing data + e.printStackTrace(); + } + }); + }, () -> Core.app.post(done)); } @Override diff --git a/net/src/io/anuke/mindustry/net/ArcNetServer.java b/net/src/io/anuke/mindustry/net/ArcNetServer.java index 0110523061..ed8496a8e2 100644 --- a/net/src/io/anuke/mindustry/net/ArcNetServer.java +++ b/net/src/io/anuke/mindustry/net/ArcNetServer.java @@ -1,23 +1,21 @@ package io.anuke.mindustry.net; -import com.dosse.upnp.UPnP; -import io.anuke.arc.Core; -import io.anuke.arc.collection.Array; +import com.dosse.upnp.*; +import io.anuke.arc.*; +import io.anuke.arc.collection.*; import io.anuke.arc.net.*; -import io.anuke.arc.util.Log; -import io.anuke.arc.util.Time; -import io.anuke.mindustry.Vars; -import io.anuke.mindustry.net.Net.SendMode; -import io.anuke.mindustry.net.Net.ServerProvider; +import io.anuke.arc.util.*; +import io.anuke.mindustry.*; +import io.anuke.mindustry.net.Net.*; import io.anuke.mindustry.net.Packets.*; -import net.jpountz.lz4.LZ4Compressor; -import net.jpountz.lz4.LZ4Factory; +import net.jpountz.lz4.*; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.channels.ClosedSelectorException; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.CopyOnWriteArraySet; +import java.io.*; +import java.nio.*; +import java.nio.channels.*; +import java.util.concurrent.*; + +import static io.anuke.mindustry.Vars.*; public class ArcNetServer implements ServerProvider{ final Server server; @@ -31,10 +29,11 @@ public class ArcNetServer implements ServerProvider{ public ArcNetServer(){ server = new Server(4096 * 2, 4096, new PacketSerializer()); - server.setDiscoveryHandler((datagramChannel, fromAddress) -> { + server.setMulticast(multicastGroup, multicastPort); + server.setDiscoveryHandler((address, handler) -> { ByteBuffer buffer = NetworkIO.writeServerData(); buffer.position(0); - datagramChannel.send(buffer, fromAddress); + handler.respond(buffer); }); NetListener listener = new NetListener(){ diff --git a/settings.gradle b/settings.gradle index 40cab3a003..25adfcd763 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,8 +1,8 @@ -include 'desktop', 'core', 'net', 'server', 'ios', 'annotations', 'tools', 'tests' +include 'desktop', 'desktop-sdl', 'core', 'net', 'server', 'ios', 'annotations', 'tools', 'tests' -def use = { String name, String path -> +def use = { String name -> include(name) - project(name).projectDir = new File(settingsDir, path) + project(name).projectDir = new File(settingsDir, "../${name.substring(1).replace(":", "/")}") } Properties properties = new Properties() @@ -21,21 +21,22 @@ if(new File(settingsDir, 'local.properties').exists()){ if(!hasProperty("release")){ if(new File(settingsDir, '../Arc').exists()){ - use(':Arc', '../Arc') - use(':Arc:arc-core', '../Arc/arc-core') - use(':Arc:extensions', '../Arc/extensions') - use(':Arc:extensions:freetype', '../Arc/extensions/freetype') - use(':Arc:extensions:recorder', '../Arc/extensions/recorder') - use(':Arc:extensions:arcnet', '../Arc/extensions/arcnet') - use(':Arc:extensions:packer', '../Arc/extensions/packer') - use(':Arc:backends', '../Arc/backends') - use(':Arc:backends:backend-lwjgl3', '../Arc/backends/backend-lwjgl3') - use(':Arc:backends:backend-android', '../Arc/backends/backend-android') - use(':Arc:backends:backend-robovm', '../Arc/backends/backend-robovm') - use(':Arc:backends:backend-headless', '../Arc/backends/backend-headless') + use(':Arc') + use(':Arc:arc-core') + use(':Arc:extensions') + use(':Arc:extensions:freetype') + use(':Arc:extensions:recorder') + use(':Arc:extensions:arcnet') + use(':Arc:extensions:packer') + use(':Arc:backends') + use(':Arc:backends:backend-sdl') + use(':Arc:backends:backend-lwjgl3') + use(':Arc:backends:backend-android') + use(':Arc:backends:backend-robovm') + use(':Arc:backends:backend-headless') } if(new File(settingsDir, '../debug').exists()){ - use(':debug', '../debug') + use(':debug') } }else{ println("Not including local repositories.") diff --git a/tests/build.gradle b/tests/build.gradle index c8c73ebfdb..93595748d0 100644 --- a/tests/build.gradle +++ b/tests/build.gradle @@ -1,3 +1,11 @@ apply plugin: "java" sourceCompatibility = 1.8 + +sourceSets{ + test{ + resources{ + srcDir "src/test/resources" + } + } +} \ No newline at end of file diff --git a/tests/src/test/java/ApplicationTests.java b/tests/src/test/java/ApplicationTests.java index 875ae50e6c..a1b9fc59d6 100644 --- a/tests/src/test/java/ApplicationTests.java +++ b/tests/src/test/java/ApplicationTests.java @@ -1,6 +1,6 @@ import io.anuke.arc.ApplicationCore; +import io.anuke.arc.Core; import io.anuke.arc.backends.headless.HeadlessApplication; -import io.anuke.arc.collection.Array; import io.anuke.arc.math.geom.Point2; import io.anuke.arc.util.Log; import io.anuke.arc.util.Time; @@ -10,12 +10,14 @@ import io.anuke.mindustry.core.GameState.State; import io.anuke.mindustry.core.*; import io.anuke.mindustry.entities.traits.BuilderTrait.BuildRequest; import io.anuke.mindustry.entities.type.BaseUnit; -import io.anuke.mindustry.entities.type.base.Spirit; -import io.anuke.mindustry.game.*; +import io.anuke.mindustry.entities.type.base.*; +import io.anuke.mindustry.game.Content; +import io.anuke.mindustry.game.Team; import io.anuke.mindustry.io.BundleLoader; import io.anuke.mindustry.io.SaveIO; import io.anuke.mindustry.maps.Map; -import io.anuke.mindustry.type.*; +import io.anuke.mindustry.type.ContentType; +import io.anuke.mindustry.type.Item; import io.anuke.mindustry.world.*; import io.anuke.mindustry.world.blocks.BlockPart; import org.junit.jupiter.api.*; @@ -215,6 +217,16 @@ public class ApplicationTests{ assertTrue(state.teams.get(defaultTeam).cores.size > 0); } + @Test + void loadOldSave(){ + resetWorld(); + SaveIO.load(Core.files.internal("build77.msav")); + + //just tests if the map was loaded properly and didn't crash, no validity checks currently + assertEquals(276, world.width()); + assertEquals(10, world.height()); + } + @Test void inventoryDeposit(){ depositTest(Blocks.surgeSmelter, Items.copper); @@ -238,8 +250,8 @@ public class ApplicationTests{ void buildingOverlap(){ initBuilding(); - Spirit d1 = (Spirit)UnitTypes.spirit.create(Team.blue); - Spirit d2 = (Spirit)UnitTypes.spirit.create(Team.blue); + Phantom d1 = (Phantom)UnitTypes.phantom.create(Team.blue); + Phantom d2 = (Phantom)UnitTypes.phantom.create(Team.blue); d1.set(10f, 20f); d2.set(10f, 20f); @@ -256,45 +268,12 @@ public class ApplicationTests{ assertTrue(world.tile(1, 1).block() instanceof BlockPart); } - @Test - void zoneEmptyWaves(){ - for(Zone zone : content.zones()){ - Array spawns = zone.rules.get().spawns; - for(int i = 1; i <= 100; i++){ - int total = 0; - for(SpawnGroup spawn : spawns){ - total += spawn.getUnitsSpawned(i); - } - - assertNotEquals(0, total, "Zone " + zone + " has no spawned enemies at wave " + i); - } - } - } - - @Test - void zoneOverflowWaves(){ - for(Zone zone : content.zones()){ - Array spawns = zone.rules.get().spawns; - - for(int i = 1; i <= 40; i++){ - int total = 0; - for(SpawnGroup spawn : spawns){ - total += spawn.getUnitsSpawned(i); - } - - if(total >= 140){ - fail("Zone '" + zone + "' has too many spawned enemies at wave " + i + " : " + total); - } - } - } - } - @Test void buildingDestruction(){ initBuilding(); - Spirit d1 = (Spirit)UnitTypes.spirit.create(Team.blue); - Spirit d2 = (Spirit)UnitTypes.spirit.create(Team.blue); + Phantom d1 = (Phantom)UnitTypes.phantom.create(Team.blue); + Phantom d2 = (Phantom)UnitTypes.phantom.create(Team.blue); d1.set(10f, 20f); d2.set(10f, 20f); @@ -321,7 +300,7 @@ public class ApplicationTests{ @Test void allBlockTest(){ - Tile[][] tiles = world.createTiles(256 + 20, 10); + Tile[][] tiles = world.createTiles(256*2 + 20, 10); world.beginMapLoad(); for(int x = 0; x < tiles.length; x++){ @@ -334,6 +313,7 @@ public class ApplicationTests{ for(int x = 5; x < tiles.length && i < content.blocks().size; ){ Block block = content.block(i++); if(block.buildVisibility.get()){ + x += block.size; tiles[x][5].setBlock(block); x += block.size; } diff --git a/tests/src/test/java/ZoneTests.java b/tests/src/test/java/ZoneTests.java index dd6f2580b9..8ad2a2f6fe 100644 --- a/tests/src/test/java/ZoneTests.java +++ b/tests/src/test/java/ZoneTests.java @@ -3,6 +3,7 @@ import io.anuke.arc.collection.ObjectSet; import io.anuke.arc.util.Structs; import io.anuke.arc.util.Time; import io.anuke.mindustry.core.GameState.State; +import io.anuke.mindustry.game.SpawnGroup; import io.anuke.mindustry.type.Item; import io.anuke.mindustry.type.Zone; import io.anuke.mindustry.world.Tile; @@ -10,6 +11,7 @@ import io.anuke.mindustry.world.blocks.storage.CoreBlock; import org.junit.jupiter.api.*; import static io.anuke.mindustry.Vars.*; +import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.DynamicTest.dynamicTest; @@ -28,7 +30,7 @@ public class ZoneTests{ } @TestFactory - DynamicTest[] testZoneResources(){ + DynamicTest[] testZoneValidity(){ Array out = new Array<>(); for(Zone zone : content.zones()){ @@ -36,6 +38,7 @@ public class ZoneTests{ zone.generator.init(zone.loadout); logic.reset(); world.loadGenerator(zone.generator); + zone.rules.accept(state.rules); ObjectSet resources = new ObjectSet<>(); boolean hasSpawnPoint = false; @@ -45,21 +48,31 @@ public class ZoneTests{ if(tile.drop() != null){ resources.add(tile.drop()); } - if(tile.block() instanceof CoreBlock){ + if(tile.block() instanceof CoreBlock && tile.getTeam() == defaultTeam){ hasSpawnPoint = true; } } } + Array spawns = state.rules.spawns; + for(int i = 1; i <= 100; i++){ + int total = 0; + for(SpawnGroup spawn : spawns){ + total += spawn.getUnitsSpawned(i); + } + + assertNotEquals(0, total, "Zone " + zone + " has no spawned enemies at wave " + i); + } + assertTrue(hasSpawnPoint, "Zone \"" + zone.name + "\" has no spawn points."); - assertTrue(world.spawner.countSpawns() > 0, "Zone \"" + zone.name + "\" has no enemy spawn points: " + world.spawner.countSpawns()); + assertTrue(world.spawner.countSpawns() > 0 || (state.rules.attackMode && !state.teams.get(waveTeam).cores.isEmpty()), "Zone \"" + zone.name + "\" has no enemy spawn points: " + world.spawner.countSpawns()); for(Item item : resources){ assertTrue(Structs.contains(zone.resources, item), "Zone \"" + zone.name + "\" is missing item in resource list: \"" + item.name + "\""); } for(Item item : zone.resources){ - assertTrue(resources.contains(item), "Zone \"" + zone.name + "\" has unnecessary item in resoruce list: \"" + item.name + "\""); + assertTrue(resources.contains(item), "Zone \"" + zone.name + "\" has unnecessary item in resource list: \"" + item.name + "\""); } })); } diff --git a/tests/src/test/resources/build77.msav b/tests/src/test/resources/build77.msav new file mode 100644 index 0000000000..8307c4fbb5 Binary files /dev/null and b/tests/src/test/resources/build77.msav differ diff --git a/tools/build.gradle b/tools/build.gradle index a855252e25..944840f4a2 100644 --- a/tools/build.gradle +++ b/tools/build.gradle @@ -5,15 +5,33 @@ sourceSets.main.java.srcDirs = ["src/"] import com.badlogic.gdx.graphics.Color -import com.badlogic.gdx.utils.IntArray +import com.badlogic.gdx.utils.* import com.badlogic.gdx.tools.texturepacker.TexturePacker import javax.imageio.ImageIO +import java.awt.Graphics2D import java.awt.image.BufferedImage -def outFolder = "../core/assets-raw/sprites_out/" def genFolder = "../core/assets-raw/sprites_out/generated/" def doAntialias = !project.hasProperty("disableAntialias") +def colorMap = new IntMap>(), colorIndexMap = new IntIntMap() + +def transformColors = { List> list -> + list.each{ colors -> + def newColors = [] + colors.each{ hexc -> + newColors += Color.valueOf(hexc) + } + + newColors.each{ color -> + colorMap.put(Color.argb8888(color), newColors) + colorIndexMap.put(Color.argb8888(color), newColors.indexOf(color)) + } + } +} + + +transformColors([["6e7080", "989aa4", "b0bac0"], ["bc5452", "ea8878", "feb380"], ["dea158", "f8c266", "ffe18f"], ["feb380", "ea8878", "bc5452"]]) def antialias = { File file -> if(!doAntialias || file.lastModified() <= 1000) return @@ -164,6 +182,37 @@ def scaleImage = { File file -> ImageIO.write(image, "png", file) } +def tileImage = { File file -> + def image = ImageIO.read(file) + + def result = new BufferedImage(image.width * 2, image.height * 2, image.getType()) + Graphics2D graphics = result.createGraphics() + graphics.drawImage(image, image.width, 0, -image.width, image.height, null) + + graphics.drawImage(image, image.width, 0, image.width, image.height, null) + + graphics.drawImage(image, image.width, image.height*2, -image.width, -image.height, null) + + graphics.drawImage(image, image.width, image.height*2, image.width, -image.height, null) + + for(int x = 0; x < result.width; x++){ + for(int y = 0; y < result.height; y++){ + int p = result.getRGB(x, y) + if(x <= y){ + List list = colorMap.get(p) + int index = colorIndexMap.get(p, -1) + + if(index != -1){ + int resultIndex = (x == y ? 1 : index == 2 ? 0 : index == 0 ? 2 : 1); + result.setRGB(x, y, Color.argb8888(list[resultIndex])) + } + } + } + } + + ImageIO.write(result, "png", file) +} + task swapColors(){ doLast{ if(project.hasProperty("colors")){ @@ -197,28 +246,6 @@ task swapColors(){ } } -task scaleSprites4x(){ - doLast{ - fileTree(dir: '../core/assets-raw/sprites_out/', include: "**/*.png").visit{ file -> - if(file.isDirectory() || file.toString().replace("\\", "/").contains("/ui/")) return - - scaleImage(file.file) - antialias(file.file) - } - } -} - -task scaleSprites(){ - finalizedBy 'genSprites' - - doLast{ - copy{ - from "../core/assets-raw/sprites/" - into "../core/assets-raw/sprites_out/" - } - } -} - task scaleImages(){ doLast{ for(def img : project.getProperty("images").split(",")){ @@ -228,66 +255,69 @@ task scaleImages(){ } } -task pack(){ - dependsOn 'cleanSprites', 'scaleSprites' - //finalizedBy 'cleanup' - +task tileImages(){ doLast{ - - fileTree(dir: '../core/assets-raw/sprites_out/', include: "**/*.png").visit{ file -> - if(file.isDirectory() || file.toString().replace("\\", "/").contains("/ui/")) return - - antialias(file.file) - } - - TexturePacker.process("core/assets-raw/sprites_out/", "core/assets/sprites/", "sprites.atlas") - - delete{ - delete fileTree(dir: '../core/assets-raw/sprites_out/', include: '**/pack.json') - } - - copy{ - from '../core/assets-raw/sprites_out/' - into '../core/assets-raw/sprites_out/' - include '**/*.json' - rename 'pack_fallback.json', "pack.json" - } - - TexturePacker.process("core/assets-raw/sprites_out/", "core/assets/sprites/", "sprites_fallback.atlas") - } - -} - -task cleanup(){ - doLast{ - delete{ - delete genFolder - delete outFolder + for(def img : project.getProperty("images").split(",")){ + println(project.getProperty("startdir") + "/" + img) + tileImage(new File(project.getProperty("startdir") + "/" + img)) } } } -task cleanSprites(){ +task pack(dependsOn: classes){ doLast{ + //cleanup old sprites delete{ delete "../core/assets-raw/sprites_out/" } + //copy in new sprites copy{ from "../core/assets-raw/sprites/" into "../core/assets-raw/sprites_out/" } + //run generation task; generate all needed sprites file(genFolder).mkdirs() - } -} + javaexec{ + main = "io.anuke.mindustry.ImagePacker" + classpath = sourceSets.main.runtimeClasspath + standardInput = System.in + workingDir = genFolder + } + + //upscale icon sprites using different method, which requires an OpenGL context + javaexec{ + if(System.getProperty("os.name").toLowerCase().contains("mac")){ + jvmArgs "-XstartOnFirstThread" + } + + jvmArgs("-Djava.awt.headless=true") + main = "io.anuke.mindustry.Upscaler" + classpath = sourceSets.main.runtimeClasspath + standardInput = System.in + workingDir = "../core/assets-raw/sprites_out/ui/icons" + } + + copy{ + from "../core/assets-raw/sprites_out/ui/icons" + into "../core/assets-raw/sprites_out/ui/" + } + + delete{ + delete "../core/assets-raw/sprites_out/ui/icons" + } + + //antialias everything except UI elements + fileTree(dir: '../core/assets-raw/sprites_out/', include: "**/*.png").visit{ file -> + if(file.isDirectory() || (file.toString().replace("\\", "/").contains("/ui/"))) return -task antialiasGen(){ - doLast{ - fileTree(dir: '../core/assets-raw/sprites_out/generated/', include: "**/*.png").visit{ file -> antialias(file.file) } + + //pack normal sprites + TexturePacker.process("core/assets-raw/sprites_out/", "core/assets/sprites/", "sprites.atlas") } } @@ -296,6 +326,7 @@ task genSprites(dependsOn: classes, type: JavaExec){ main = "io.anuke.mindustry.ImagePacker" classpath = sourceSets.main.runtimeClasspath + jvmArgs("-Djava.awt.headless=true") standardInput = System.in workingDir = genFolder } diff --git a/tools/src/io/anuke/mindustry/Generators.java b/tools/src/io/anuke/mindustry/Generators.java index 443f81a883..deabc56a7b 100644 --- a/tools/src/io/anuke/mindustry/Generators.java +++ b/tools/src/io/anuke/mindustry/Generators.java @@ -70,7 +70,7 @@ public class Generators{ ImagePacker.generate("block-icons", () -> { Image colors = new Image(content.blocks().size, 1); - Color outlineColor = Color.valueOf("4d4e58"); + Color outlineColor = Color.valueOf("404049"); for(Block block : content.blocks()){ TextureRegion[] regions = block.getGeneratedIcons(); @@ -143,17 +143,15 @@ public class Generators{ } } - if(regions.length > 1){ - image.save(block.name + "-icon-full"); - } + 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; + if(icon.size == 0) continue; Image scaled = new Image(icon.size, icon.size); scaled.drawScaled(image); - scaled.save(block.name + "-icon-" + icon.name()); + scaled.save("../ui/" + block.name + "-icon-" + icon.name()); } Color average = new Color(); diff --git a/tools/src/io/anuke/mindustry/SquareMarcher.java b/tools/src/io/anuke/mindustry/SquareMarcher.java new file mode 100644 index 0000000000..cbefa2c0c1 --- /dev/null +++ b/tools/src/io/anuke/mindustry/SquareMarcher.java @@ -0,0 +1,212 @@ +package io.anuke.mindustry; + +import io.anuke.arc.Core; +import io.anuke.arc.files.FileHandle; +import io.anuke.arc.graphics.Color; +import io.anuke.arc.graphics.Pixmap; +import io.anuke.arc.graphics.g2d.Draw; +import io.anuke.arc.graphics.g2d.Fill; +import io.anuke.arc.graphics.glutils.FrameBuffer; +import io.anuke.arc.util.ScreenUtils; +import io.anuke.arc.util.Tmp; + +public class SquareMarcher{ + final int resolution; + FrameBuffer buffer; + + SquareMarcher(int resolution){ + this.resolution = resolution; + this.buffer = new FrameBuffer(resolution, resolution); + } + + void render(Pixmap pixmap, FileHandle file){ + boolean[][] grid = new boolean[pixmap.getWidth()][pixmap.getHeight()]; + + for(int x = 0; x < pixmap.getWidth(); x++){ + for(int y = 0; y < pixmap.getHeight(); y++){ + Tmp.c1.set(pixmap.getPixel(x, y)); + grid[x][pixmap.getHeight() - 1 - y] = Tmp.c1.a > 0.01f; + } + } + + float xscl = resolution / (float)pixmap.getWidth(), yscl = resolution / (float)pixmap.getHeight(); + float scl = xscl; + + Draw.flush(); + Draw.proj().setOrtho(-xscl / 2f, -yscl / 2f, resolution, resolution); + + buffer.begin(); + Core.graphics.clear(Color.CLEAR); + Draw.color(Color.WHITE); + + for(int x = -1; x < pixmap.getWidth(); x++){ + for(int y = -1; y < pixmap.getHeight(); y++){ + int index = index(x, y, pixmap.getWidth(), pixmap.getHeight(), grid); + + float leftx = x * xscl, boty = y * yscl, rightx = x * xscl + xscl, topy = y * xscl + yscl, + midx = x * xscl + xscl / 2f, midy = y * yscl + yscl / 2f; + + switch(index){ + case 0: + break; + case 1: + Fill.tri( + leftx, midy, + leftx, topy, + midx, topy + ); + break; + case 2: + Fill.tri( + midx, topy, + rightx, topy, + rightx, midy + ); + break; + case 3: + Fill.crect(leftx, midy, scl, scl / 2f); + break; + case 4: + Fill.tri( + midx, boty, + rightx, boty, + rightx, midy + ); + break; + case 5: + //ambiguous + + //7 + Fill.tri( + leftx, midy, + midx, midy, + midx, boty + ); + + //13 + Fill.tri( + midx, topy, + midx, midy, + rightx, midy + ); + + Fill.crect(leftx, midy, scl / 2f, scl / 2f); + Fill.crect(midx, boty, scl / 2f, scl / 2f); + + break; + case 6: + Fill.crect(midx, boty, scl / 2f, scl); + break; + case 7: + //invert triangle + Fill.tri( + leftx, midy, + midx, midy, + midx, boty + ); + + //3 + Fill.crect(leftx, midy, scl, scl / 2f); + + Fill.crect(midx, boty, scl / 2f, scl / 2f); + break; + case 8: + Fill.tri( + leftx, boty, + leftx, midy, + midx, boty + ); + break; + case 9: + Fill.crect(leftx, boty, scl / 2f, scl); + break; + case 10: + //ambiguous + + //11 + Fill.tri( + midx, boty, + midx, midy, + rightx, midy + ); + + //14 + Fill.tri( + leftx, midy, + midx, midy, + midx, topy + ); + + Fill.crect(midx, midy, scl / 2f, scl / 2f); + Fill.crect(leftx, boty, scl / 2f, scl / 2f); + + break; + case 11: + //invert triangle + + Fill.tri( + midx, boty, + midx, midy, + rightx, midy + ); + + //3 + Fill.crect(leftx, midy, scl, scl / 2f); + + Fill.crect(leftx, boty, scl / 2f, scl / 2f); + break; + case 12: + Fill.crect(leftx, boty, scl, scl / 2f); + break; + case 13: + //invert triangle + + Fill.tri( + midx, topy, + midx, midy, + rightx, midy + ); + + //12 + Fill.crect(leftx, boty, scl, scl / 2f); + + Fill.crect(leftx, midy, scl / 2f, scl / 2f); + break; + case 14: + //invert triangle + + Fill.tri( + leftx, midy, + midx, midy, + midx, topy + ); + + //12 + Fill.crect(leftx, boty, scl, scl / 2f); + + Fill.crect(midx, midy, scl / 2f, scl / 2f); + break; + case 15: + Fill.square(midx, midy, scl / 2f); + break; + } + } + } + + Draw.flush(); + ScreenUtils.saveScreenshot(file, 0, 0, resolution, resolution); + buffer.end(); + } + + int index(int x, int y, int w, int h, boolean[][] grid){ + int botleft = sample(grid, x, y); + int botright = sample(grid, x + 1, y); + int topright = sample(grid, x + 1, y + 1); + int topleft = sample(grid, x, y + 1); + return (botleft << 3) | (botright << 2) | (topright << 1) | topleft; + } + + int sample(boolean[][] grid, int x, int y){ + return (x < 0 || y < 0 || x >= grid.length || y >= grid.length) ? 0 : grid[x][y] ? 1 : 0; + } +} diff --git a/tools/src/io/anuke/mindustry/Upscaler.java b/tools/src/io/anuke/mindustry/Upscaler.java new file mode 100644 index 0000000000..c2fcdb608a --- /dev/null +++ b/tools/src/io/anuke/mindustry/Upscaler.java @@ -0,0 +1,61 @@ +package io.anuke.mindustry; + +import io.anuke.arc.*; +import io.anuke.arc.backends.sdl.*; +import io.anuke.arc.files.*; +import io.anuke.arc.graphics.*; +import io.anuke.arc.graphics.g2d.*; +import io.anuke.arc.util.*; + +public class Upscaler{ + static Res[] resolutions = { + new Res(Vars.iconsizesmall, "-small"), + new Res(Vars.iconsizemed, "-med"), + new Res(Vars.iconsize, ""), + }; + + public static void main(String[] args){ + new SdlApplication(new ApplicationListener(){ + @Override + public void init(){ + scale(); + } + }, new SdlConfig(){{ + initialVisible = false; + }}); + } + + static void scale(){ + Core.batch = new SpriteBatch(); + Core.atlas = new TextureAtlas(); + Core.atlas.addRegion("white", Pixmaps.blankTextureRegion()); + FileHandle file = Core.files.local(""); + + Log.info("Upscaling icons..."); + Time.mark(); + FileHandle[] list = file.list(); + + for(Res res : resolutions){ + SquareMarcher marcher = new SquareMarcher(res.size); + + for(FileHandle img : list){ + if(img.extension().equals("png")){ + marcher.render(new Pixmap(img), img.sibling(img.nameWithoutExtension() + res.suffix + ".png")); + } + } + } + + Log.info("Done upscaling icons in &lm{0}&lgs.", Time.elapsed()/1000f); + Core.app.exit(); + } + + static class Res{ + final int size; + final String suffix; + + public Res(int size, String suffix){ + this.size = size; + this.suffix = suffix; + } + } +} diff --git a/update_wiki.sh b/update_wiki.sh new file mode 100755 index 0000000000..f18e7a651c --- /dev/null +++ b/update_wiki.sh @@ -0,0 +1,9 @@ +git config --global user.name "Wiki Updater" +git clone --depth=1 --branch=master https://github.com/MindustryGame/wiki ../wiki +git clone --depth=1 --branch=master https://github.com/Anuken/Mindustry-Wiki-Generator ../Mindustry-Wiki-Generator +cd ../Mindustry-Wiki-Generator +./gradlew run +cd ../wiki +git add . +git commit -m "Update to match commit ${TRAVIS_COMMIT}" +git push https://Anuken:${GH_PUSH_TOKEN}@github.com/MindustryGame/wiki